mac80211: clean up mesh code

There's various code with strange indentation,
questionable loop and locking constructs, etc.

The bigger change is moving the "sdata" argument
to the first argument of all functions, like all
other mac80211 functions that have one.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2013-02-15 14:40:31 +01:00
parent 93c78c5deb
commit bf7cd94dcc
10 changed files with 252 additions and 263 deletions

View File

@ -1500,13 +1500,13 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
return -ENOENT; return -ENOENT;
} }
err = mesh_path_add(dst, sdata); err = mesh_path_add(sdata, dst);
if (err) { if (err) {
rcu_read_unlock(); rcu_read_unlock();
return err; return err;
} }
mpath = mesh_path_lookup(dst, sdata); mpath = mesh_path_lookup(sdata, dst);
if (!mpath) { if (!mpath) {
rcu_read_unlock(); rcu_read_unlock();
return -ENXIO; return -ENXIO;
@ -1518,12 +1518,12 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
} }
static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
u8 *dst) u8 *dst)
{ {
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (dst) if (dst)
return mesh_path_del(dst, sdata); return mesh_path_del(sdata, dst);
mesh_path_flush_by_iface(sdata); mesh_path_flush_by_iface(sdata);
return 0; return 0;
@ -1547,7 +1547,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy,
return -ENOENT; return -ENOENT;
} }
mpath = mesh_path_lookup(dst, sdata); mpath = mesh_path_lookup(sdata, dst);
if (!mpath) { if (!mpath) {
rcu_read_unlock(); rcu_read_unlock();
return -ENOENT; return -ENOENT;
@ -1611,7 +1611,7 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
sdata = IEEE80211_DEV_TO_SUB_IF(dev); sdata = IEEE80211_DEV_TO_SUB_IF(dev);
rcu_read_lock(); rcu_read_lock();
mpath = mesh_path_lookup(dst, sdata); mpath = mesh_path_lookup(sdata, dst);
if (!mpath) { if (!mpath) {
rcu_read_unlock(); rcu_read_unlock();
return -ENOENT; return -ENOENT;
@ -1632,7 +1632,7 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
sdata = IEEE80211_DEV_TO_SUB_IF(dev); sdata = IEEE80211_DEV_TO_SUB_IF(dev);
rcu_read_lock(); rcu_read_lock();
mpath = mesh_path_lookup_by_idx(idx, sdata); mpath = mesh_path_lookup_by_idx(sdata, idx);
if (!mpath) { if (!mpath) {
rcu_read_unlock(); rcu_read_unlock();
return -ENOENT; return -ENOENT;

View File

@ -1173,8 +1173,7 @@ static void __exit ieee80211_exit(void)
rc80211_minstrel_ht_exit(); rc80211_minstrel_ht_exit();
rc80211_minstrel_exit(); rc80211_minstrel_exit();
if (mesh_allocated) ieee80211s_stop();
ieee80211s_stop();
ieee80211_iface_exit(); ieee80211_iface_exit();

View File

@ -17,7 +17,7 @@
#define TMR_RUNNING_MP 1 #define TMR_RUNNING_MP 1
#define TMR_RUNNING_MPR 2 #define TMR_RUNNING_MPR 2
int mesh_allocated; static int mesh_allocated;
static struct kmem_cache *rm_cache; static struct kmem_cache *rm_cache;
bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt)
@ -36,6 +36,8 @@ void ieee80211s_init(void)
void ieee80211s_stop(void) void ieee80211s_stop(void)
{ {
if (!mesh_allocated)
return;
mesh_pathtbl_unregister(); mesh_pathtbl_unregister();
kmem_cache_destroy(rm_cache); 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_cc_id == ie->mesh_config->meshconf_congest) &&
(ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) && (ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) &&
(ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth)))
goto mismatch; return false;
ieee80211_sta_get_rates(local, ie, ieee80211_get_sdata_band(sdata), ieee80211_sta_get_rates(local, ie, ieee80211_get_sdata_band(sdata),
&basic_rates); &basic_rates);
if (sdata->vif.bss_conf.basic_rates != 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, ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan,
ie->ht_operation, &sta_chan_def); ie->ht_operation, &sta_chan_def);
if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef, if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef,
&sta_chan_def)) &sta_chan_def))
goto mismatch; return false;
return true; return true;
mismatch:
return false;
} }
/** /**
@ -118,7 +118,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie)
{ {
return (ie->mesh_config->meshconf_cap & 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) if (!sdata->u.mesh.rmc)
return; 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_for_each_entry_safe(p, n, &rmc->bucket[i], list) {
list_del(&p->list); list_del(&p->list);
kmem_cache_free(rm_cache, p); kmem_cache_free(rm_cache, p);
} }
}
kfree(rmc); kfree(rmc);
sdata->u.mesh.rmc = NULL; 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. * mesh_rmc_check - Check frame in recent multicast cache and add if absent.
* *
* @sdata: interface
* @sa: source address * @sa: source address
* @mesh_hdr: mesh_header * @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 * received this frame lately. If the frame is not in the cache, it is added to
* it. * it.
*/ */
int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, int mesh_rmc_check(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata) const u8 *sa, struct ieee80211s_hdr *mesh_hdr)
{ {
struct mesh_rmc *rmc = sdata->u.mesh.rmc; struct mesh_rmc *rmc = sdata->u.mesh.rmc;
u32 seqnum = 0; 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) { list_for_each_entry_safe(p, n, &rmc->bucket[idx], list) {
++entries; ++entries;
if (time_after(jiffies, p->exp_time) || if (time_after(jiffies, p->exp_time) ||
(entries == RMC_QUEUE_MAX_LEN)) { entries == RMC_QUEUE_MAX_LEN) {
list_del(&p->list); list_del(&p->list);
kmem_cache_free(rm_cache, p); kmem_cache_free(rm_cache, p);
--entries; --entries;
} else if ((seqnum == p->seqnum) && } else if ((seqnum == p->seqnum) && ether_addr_equal(sa, p->sa))
(ether_addr_equal(sa, p->sa)))
return -1; return -1;
} }
@ -253,8 +254,8 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
return 0; return 0;
} }
int int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata,
mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) struct sk_buff *skb)
{ {
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u8 *pos, neighbors; u8 *pos, neighbors;
@ -285,19 +286,18 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
/* Mesh capability */ /* Mesh capability */
*pos = IEEE80211_MESHCONF_CAPAB_FORWARDING; *pos = IEEE80211_MESHCONF_CAPAB_FORWARDING;
*pos |= ifmsh->accepting_plinks ? *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 */ /* Mesh PS mode. See IEEE802.11-2012 8.4.2.100.8 */
*pos |= ifmsh->ps_peers_deep_sleep ? *pos |= ifmsh->ps_peers_deep_sleep ?
IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL : 0x00; IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL : 0x00;
*pos++ |= ifmsh->adjusting_tbtt ? *pos++ |= ifmsh->adjusting_tbtt ?
IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00;
*pos++ = 0x00; *pos++ = 0x00;
return 0; return 0;
} }
int int mesh_add_meshid_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
{ {
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u8 *pos; u8 *pos;
@ -314,8 +314,8 @@ mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
return 0; return 0;
} }
int mesh_add_awake_window_ie(struct sk_buff *skb, static int mesh_add_awake_window_ie(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata) struct sk_buff *skb)
{ {
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u8 *pos; u8 *pos;
@ -337,8 +337,8 @@ int mesh_add_awake_window_ie(struct sk_buff *skb,
return 0; return 0;
} }
int int mesh_add_vendor_ies(struct ieee80211_sub_if_data *sdata,
mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) struct sk_buff *skb)
{ {
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u8 offset, len; u8 offset, len;
@ -361,8 +361,7 @@ mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
return 0; return 0;
} }
int int mesh_add_rsn_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
{ {
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u8 len = 0; u8 len = 0;
@ -390,8 +389,8 @@ mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
return 0; return 0;
} }
int mesh_add_ds_params_ie(struct sk_buff *skb, static int mesh_add_ds_params_ie(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata) struct sk_buff *skb)
{ {
struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_channel *chan; struct ieee80211_channel *chan;
@ -417,8 +416,8 @@ int mesh_add_ds_params_ie(struct sk_buff *skb,
return 0; return 0;
} }
int mesh_add_ht_cap_ie(struct sk_buff *skb, int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata) struct sk_buff *skb)
{ {
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
enum ieee80211_band band = ieee80211_get_sdata_band(sdata); 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; return 0;
} }
int mesh_add_ht_oper_ie(struct sk_buff *skb, int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata) struct sk_buff *skb)
{ {
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_chanctx_conf *chanctx_conf;
@ -475,6 +474,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb,
return 0; return 0;
} }
static void ieee80211_mesh_path_timer(unsigned long data) static void ieee80211_mesh_path_timer(unsigned long data)
{ {
struct ieee80211_sub_if_data *sdata = 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 * 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 * @fc: frame control field
* @meshda: destination address in the mesh * @meshda: destination address in the mesh
* @meshsa: source address address in the mesh. Same as TA, as frame is * @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 * ieee80211_new_mesh_header - create a new mesh header
* @meshhdr: uninitialized mesh header
* @sdata: mesh interface to be used * @sdata: mesh interface to be used
* @meshhdr: uninitialized mesh header
* @addr4or5: 1st address in the ae header, which may correspond to address 4 * @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 * (if addr6 is NULL) or address 5 (if addr6 is present). It may
* be NULL. * be NULL.
@ -561,32 +561,38 @@ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
* *
* Return the header length. * Return the header length.
*/ */
int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, int ieee80211_new_mesh_header(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata, char *addr4or5, struct ieee80211s_hdr *meshhdr,
char *addr6) const char *addr4or5, const char *addr6)
{ {
int aelen = 0; if (WARN_ON(!addr4or5 && addr6))
BUG_ON(!addr4or5 && addr6); return 0;
memset(meshhdr, 0, sizeof(*meshhdr)); memset(meshhdr, 0, sizeof(*meshhdr));
meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; 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); put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum);
sdata->u.mesh.mesh_seqnum++; sdata->u.mesh.mesh_seqnum++;
if (addr4or5 && !addr6) { if (addr4or5 && !addr6) {
meshhdr->flags |= MESH_FLAGS_AE_A4; meshhdr->flags |= MESH_FLAGS_AE_A4;
aelen += ETH_ALEN;
memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN);
return 2 * ETH_ALEN;
} else if (addr4or5 && addr6) { } else if (addr4or5 && addr6) {
meshhdr->flags |= MESH_FLAGS_AE_A5_A6; meshhdr->flags |= MESH_FLAGS_AE_A5_A6;
aelen += 2 * ETH_ALEN;
memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN);
memcpy(meshhdr->eaddr2, addr6, 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, static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata)
struct ieee80211_if_mesh *ifmsh)
{ {
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u32 changed; u32 changed;
ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); 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); ieee80211_mbss_info_change_notify(sdata, changed);
mod_timer(&ifmsh->housekeeping_timer, 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) 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; *pos++ = 0x0;
if (ieee80211_add_srates_ie(sdata, skb, true, band) || 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; goto out_free;
bcn->head_len = skb->len; 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; bcn->tail = bcn->head + bcn->head_len;
if (ieee80211_add_ext_srates_ie(sdata, skb, true, band) || if (ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
mesh_add_rsn_ie(skb, sdata) || mesh_add_rsn_ie(sdata, skb) ||
mesh_add_ht_cap_ie(skb, sdata) || mesh_add_ht_cap_ie(sdata, skb) ||
mesh_add_ht_oper_ie(skb, sdata) || mesh_add_ht_oper_ie(sdata, skb) ||
mesh_add_meshid_ie(skb, sdata) || mesh_add_meshid_ie(sdata, skb) ||
mesh_add_meshconf_ie(skb, sdata) || mesh_add_meshconf_ie(sdata, skb) ||
mesh_add_awake_window_ie(skb, sdata) || mesh_add_awake_window_ie(sdata, skb) ||
mesh_add_vendor_ies(skb, sdata)) mesh_add_vendor_ies(sdata, skb))
goto out_free; goto out_free;
bcn->tail_len = skb->len; bcn->tail_len = skb->len;
@ -1039,7 +1046,7 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
mesh_mpp_table_grow(); mesh_mpp_table_grow();
if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) 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)) if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags))
ieee80211_mesh_rootpath(sdata); ieee80211_mesh_rootpath(sdata);

View File

@ -26,12 +26,12 @@
* @MESH_PATH_ACTIVE: the mesh path can be used for forwarding * @MESH_PATH_ACTIVE: the mesh path can be used for forwarding
* @MESH_PATH_RESOLVING: the discovery process is running for this mesh path * @MESH_PATH_RESOLVING: the discovery process is running for this mesh path
* @MESH_PATH_SN_VALID: the mesh path contains a valid destination sequence * @MESH_PATH_SN_VALID: the mesh path contains a valid destination sequence
* number * number
* @MESH_PATH_FIXED: the mesh path has been manually set and should not be * @MESH_PATH_FIXED: the mesh path has been manually set and should not be
* modified * modified
* @MESH_PATH_RESOLVED: the mesh path can has been resolved * @MESH_PATH_RESOLVED: the mesh path can has been resolved
* @MESH_PATH_REQ_QUEUED: there is an unsent path request for this destination * @MESH_PATH_REQ_QUEUED: there is an unsent path request for this destination
* already queued up, waiting for the discovery process to start. * already queued up, waiting for the discovery process to start.
* *
* MESH_PATH_RESOLVED is used by the mesh path timer to * MESH_PATH_RESOLVED is used by the mesh path timer to
* decide when to stop or cancel the mesh path discovery. * decide when to stop or cancel the mesh path discovery.
@ -73,16 +73,16 @@ enum mesh_deferred_task_flags {
* @dst: mesh path destination mac address * @dst: mesh path destination mac address
* @sdata: mesh subif * @sdata: mesh subif
* @next_hop: mesh neighbor to which frames for this destination will be * @next_hop: mesh neighbor to which frames for this destination will be
* forwarded * forwarded
* @timer: mesh path discovery timer * @timer: mesh path discovery timer
* @frame_queue: pending queue for frames sent to this destination while the * @frame_queue: pending queue for frames sent to this destination while the
* path is unresolved * path is unresolved
* @sn: target sequence number * @sn: target sequence number
* @metric: current metric to this destination * @metric: current metric to this destination
* @hop_count: hops to destination * @hop_count: hops to destination
* @exp_time: in jiffies, when the path will expire or when it expired * @exp_time: in jiffies, when the path will expire or when it expired
* @discovery_timeout: timeout (lapse in jiffies) used for the last discovery * @discovery_timeout: timeout (lapse in jiffies) used for the last discovery
* retry * retry
* @discovery_retries: number of discovery retries * @discovery_retries: number of discovery retries
* @flags: mesh path flags, as specified on &enum mesh_path_flags * @flags: mesh path flags, as specified on &enum mesh_path_flags
* @state_lock: mesh path state lock used to protect changes to the * @state_lock: mesh path state lock used to protect changes to the
@ -206,38 +206,33 @@ struct mesh_rmc {
/* Various */ /* Various */
int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
const u8 *da, const u8 *sa); const u8 *da, const u8 *sa);
int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, int ieee80211_new_mesh_header(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata, char *addr4or5, struct ieee80211s_hdr *meshhdr,
char *addr6); const char *addr4or5, const char *addr6);
int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, int mesh_rmc_check(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata); const u8 *addr, struct ieee80211s_hdr *mesh_hdr);
bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
struct ieee802_11_elems *ie); struct ieee802_11_elems *ie);
void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); void mesh_ids_set_default(struct ieee80211_if_mesh *mesh);
void mesh_mgmt_ies_add(struct sk_buff *skb, void mesh_mgmt_ies_add(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata); struct sk_buff *skb);
int mesh_add_meshconf_ie(struct sk_buff *skb, int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata); struct sk_buff *skb);
int mesh_add_meshid_ie(struct sk_buff *skb, int mesh_add_meshid_ie(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata); struct sk_buff *skb);
int mesh_add_rsn_ie(struct sk_buff *skb, int mesh_add_rsn_ie(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata); struct sk_buff *skb);
int mesh_add_awake_window_ie(struct sk_buff *skb, int mesh_add_vendor_ies(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata); struct sk_buff *skb);
int mesh_add_vendor_ies(struct sk_buff *skb, int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata); struct sk_buff *skb);
int mesh_add_ds_params_ie(struct sk_buff *skb, int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata); struct sk_buff *skb);
int mesh_add_ht_cap_ie(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata);
int mesh_add_ht_oper_ie(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata);
void mesh_rmc_free(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); int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
void ieee80211s_init(void); void ieee80211s_init(void);
void ieee80211s_update_metric(struct ieee80211_local *local, void ieee80211s_update_metric(struct ieee80211_local *local,
struct sta_info *sta, struct sk_buff *skb); struct sta_info *sta, struct sk_buff *skb);
void ieee80211s_stop(void);
void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata);
@ -263,31 +258,32 @@ void ieee80211_mps_frame_release(struct sta_info *sta,
struct ieee802_11_elems *elems); struct ieee802_11_elems *elems);
/* Mesh paths */ /* Mesh paths */
int mesh_nexthop_lookup(struct sk_buff *skb, int mesh_nexthop_lookup(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata); struct sk_buff *skb);
int mesh_nexthop_resolve(struct sk_buff *skb, int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata); struct sk_buff *skb);
void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata);
struct mesh_path *mesh_path_lookup(const u8 *dst, struct mesh_path *mesh_path_lookup(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata); const u8 *dst);
struct mesh_path *mpp_path_lookup(u8 *dst, struct mesh_path *mpp_path_lookup(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata); const u8 *dst);
int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata); int mpp_path_add(struct ieee80211_sub_if_data *sdata,
struct mesh_path *mesh_path_lookup_by_idx(int idx, const u8 *dst, const u8 *mpp);
struct ieee80211_sub_if_data *sdata); struct mesh_path *
mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx);
void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop);
void mesh_path_expire(struct ieee80211_sub_if_data *sdata); void mesh_path_expire(struct ieee80211_sub_if_data *sdata);
void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt, size_t len); struct ieee80211_mgmt *mgmt, size_t len);
int mesh_path_add(const u8 *dst, struct ieee80211_sub_if_data *sdata); int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst);
int mesh_path_add_gate(struct mesh_path *mpath); int mesh_path_add_gate(struct mesh_path *mpath);
int mesh_path_send_to_gates(struct mesh_path *mpath); int mesh_path_send_to_gates(struct mesh_path *mpath);
int mesh_gate_num(struct ieee80211_sub_if_data *sdata); int mesh_gate_num(struct ieee80211_sub_if_data *sdata);
/* Mesh plinks */ /* Mesh plinks */
void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
u8 *hw_addr, u8 *hw_addr, struct ieee802_11_elems *ie);
struct ieee802_11_elems *ie);
bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie);
u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);
void mesh_plink_broken(struct sta_info *sta); void mesh_plink_broken(struct sta_info *sta);
@ -304,19 +300,19 @@ void mesh_sta_cleanup(struct sta_info *sta);
void mesh_mpath_table_grow(void); void mesh_mpath_table_grow(void);
void mesh_mpp_table_grow(void); void mesh_mpp_table_grow(void);
/* Mesh paths */ /* Mesh paths */
int mesh_path_error_tx(u8 ttl, const u8 *target, __le32 target_sn, int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
__le16 target_rcode, const u8 *ra, u8 ttl, const u8 *target, __le32 target_sn,
struct ieee80211_sub_if_data *sdata); __le16 target_rcode, const u8 *ra);
void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta);
void mesh_path_flush_pending(struct mesh_path *mpath); void mesh_path_flush_pending(struct mesh_path *mpath);
void mesh_path_tx_pending(struct mesh_path *mpath); void mesh_path_tx_pending(struct mesh_path *mpath);
int mesh_pathtbl_init(void); int mesh_pathtbl_init(void);
void mesh_pathtbl_unregister(void); void mesh_pathtbl_unregister(void);
int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata); int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr);
void mesh_path_timer(unsigned long data); void mesh_path_timer(unsigned long data);
void mesh_path_flush_by_nexthop(struct sta_info *sta); void mesh_path_flush_by_nexthop(struct sta_info *sta);
void mesh_path_discard_frame(struct sk_buff *skb, void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata); struct sk_buff *skb);
void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata);
void mesh_path_restart(struct ieee80211_sub_if_data *sdata); void mesh_path_restart(struct ieee80211_sub_if_data *sdata);
void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);
@ -325,8 +321,6 @@ bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
extern int mesh_paths_generation; extern int mesh_paths_generation;
#ifdef CONFIG_MAC80211_MESH #ifdef CONFIG_MAC80211_MESH
extern int mesh_allocated;
static inline static inline
u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
{ {
@ -371,8 +365,8 @@ void mesh_plink_quiesce(struct sta_info *sta);
void mesh_plink_restart(struct sta_info *sta); void mesh_plink_restart(struct sta_info *sta);
void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata);
void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata);
void ieee80211s_stop(void);
#else #else
#define mesh_allocated 0
static inline void static inline void
ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {}
static inline void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) static inline void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
@ -385,6 +379,7 @@ static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata)
{ return false; } { return false; }
static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata)
{} {}
static inline void ieee80211s_stop(void) {}
#endif #endif
#endif /* IEEE80211S_H */ #endif /* IEEE80211S_H */

View File

@ -238,9 +238,9 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata,
* also acquires in the TX path. To avoid a deadlock we don't transmit the * also acquires in the TX path. To avoid a deadlock we don't transmit the
* frame directly but add it to the pending queue instead. * frame directly but add it to the pending queue instead.
*/ */
int mesh_path_error_tx(u8 ttl, const u8 *target, __le32 target_sn, int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
__le16 target_rcode, const u8 *ra, u8 ttl, const u8 *target, __le32 target_sn,
struct ieee80211_sub_if_data *sdata) __le16 target_rcode, const u8 *ra)
{ {
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct sk_buff *skb; struct sk_buff *skb;
@ -430,7 +430,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
process = false; process = false;
fresh_info = false; fresh_info = false;
} else { } else {
mpath = mesh_path_lookup(orig_addr, sdata); mpath = mesh_path_lookup(sdata, orig_addr);
if (mpath) { if (mpath) {
spin_lock_bh(&mpath->state_lock); spin_lock_bh(&mpath->state_lock);
if (mpath->flags & MESH_PATH_FIXED) if (mpath->flags & MESH_PATH_FIXED)
@ -445,8 +445,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
} }
} }
} else { } else {
mesh_path_add(orig_addr, sdata); mesh_path_add(sdata, orig_addr);
mpath = mesh_path_lookup(orig_addr, sdata); mpath = mesh_path_lookup(sdata, orig_addr);
if (!mpath) { if (!mpath) {
rcu_read_unlock(); rcu_read_unlock();
return 0; return 0;
@ -478,7 +478,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
else { else {
fresh_info = true; fresh_info = true;
mpath = mesh_path_lookup(ta, sdata); mpath = mesh_path_lookup(sdata, ta);
if (mpath) { if (mpath) {
spin_lock_bh(&mpath->state_lock); spin_lock_bh(&mpath->state_lock);
if ((mpath->flags & MESH_PATH_FIXED) || if ((mpath->flags & MESH_PATH_FIXED) ||
@ -486,8 +486,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
(last_hop_metric > mpath->metric))) (last_hop_metric > mpath->metric)))
fresh_info = false; fresh_info = false;
} else { } else {
mesh_path_add(ta, sdata); mesh_path_add(sdata, ta);
mpath = mesh_path_lookup(ta, sdata); mpath = mesh_path_lookup(sdata, ta);
if (!mpath) { if (!mpath) {
rcu_read_unlock(); rcu_read_unlock();
return 0; return 0;
@ -553,7 +553,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
} else if (is_broadcast_ether_addr(target_addr) && } else if (is_broadcast_ether_addr(target_addr) &&
(target_flags & IEEE80211_PREQ_TO_FLAG)) { (target_flags & IEEE80211_PREQ_TO_FLAG)) {
rcu_read_lock(); rcu_read_lock();
mpath = mesh_path_lookup(orig_addr, sdata); mpath = mesh_path_lookup(sdata, orig_addr);
if (mpath) { if (mpath) {
if (flags & IEEE80211_PREQ_PROACTIVE_PREP_FLAG) { if (flags & IEEE80211_PREQ_PROACTIVE_PREP_FLAG) {
reply = true; reply = true;
@ -568,7 +568,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
rcu_read_unlock(); rcu_read_unlock();
} else { } else {
rcu_read_lock(); rcu_read_lock();
mpath = mesh_path_lookup(target_addr, sdata); mpath = mesh_path_lookup(sdata, target_addr);
if (mpath) { if (mpath) {
if ((!(mpath->flags & MESH_PATH_SN_VALID)) || if ((!(mpath->flags & MESH_PATH_SN_VALID)) ||
SN_LT(mpath->sn, target_sn)) { SN_LT(mpath->sn, target_sn)) {
@ -678,7 +678,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
} }
rcu_read_lock(); rcu_read_lock();
mpath = mesh_path_lookup(orig_addr, sdata); mpath = mesh_path_lookup(sdata, orig_addr);
if (mpath) if (mpath)
spin_lock_bh(&mpath->state_lock); spin_lock_bh(&mpath->state_lock);
else else
@ -736,7 +736,7 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
target_rcode = PERR_IE_TARGET_RCODE(perr_elem); target_rcode = PERR_IE_TARGET_RCODE(perr_elem);
rcu_read_lock(); rcu_read_lock();
mpath = mesh_path_lookup(target_addr, sdata); mpath = mesh_path_lookup(sdata, target_addr);
if (mpath) { if (mpath) {
struct sta_info *sta; struct sta_info *sta;
@ -751,9 +751,10 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
spin_unlock_bh(&mpath->state_lock); spin_unlock_bh(&mpath->state_lock);
if (!ifmsh->mshcfg.dot11MeshForwarding) if (!ifmsh->mshcfg.dot11MeshForwarding)
goto endperr; goto endperr;
mesh_path_error_tx(ttl, target_addr, cpu_to_le32(target_sn), mesh_path_error_tx(sdata, ttl, target_addr,
cpu_to_le32(target_sn),
cpu_to_le16(target_rcode), cpu_to_le16(target_rcode),
broadcast_addr, sdata); broadcast_addr);
} else } else
spin_unlock_bh(&mpath->state_lock); spin_unlock_bh(&mpath->state_lock);
} }
@ -801,10 +802,10 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
metric_txsta = airtime_link_metric_get(local, sta); metric_txsta = airtime_link_metric_get(local, sta);
mpath = mesh_path_lookup(orig_addr, sdata); mpath = mesh_path_lookup(sdata, orig_addr);
if (!mpath) { if (!mpath) {
mesh_path_add(orig_addr, sdata); mesh_path_add(sdata, orig_addr);
mpath = mesh_path_lookup(orig_addr, sdata); mpath = mesh_path_lookup(sdata, orig_addr);
if (!mpath) { if (!mpath) {
rcu_read_unlock(); rcu_read_unlock();
sdata->u.mesh.mshstats.dropped_frames_no_route++; sdata->u.mesh.mshstats.dropped_frames_no_route++;
@ -861,8 +862,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt, struct ieee80211_mgmt *mgmt, size_t len)
size_t len)
{ {
struct ieee802_11_elems elems; struct ieee802_11_elems elems;
size_t baselen; size_t baselen;
@ -1006,7 +1006,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
rcu_read_lock(); rcu_read_lock();
mpath = mesh_path_lookup(preq_node->dst, sdata); mpath = mesh_path_lookup(sdata, preq_node->dst);
if (!mpath) if (!mpath)
goto enddiscovery; goto enddiscovery;
@ -1076,8 +1076,8 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
* Returns: 0 if the next hop was found and -ENOENT if the frame was queued. * Returns: 0 if the next hop was found and -ENOENT if the frame was queued.
* skb is freeed here if no mpath could be allocated. * skb is freeed here if no mpath could be allocated.
*/ */
int mesh_nexthop_resolve(struct sk_buff *skb, int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata) struct sk_buff *skb)
{ {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@ -1091,17 +1091,17 @@ int mesh_nexthop_resolve(struct sk_buff *skb,
return 0; return 0;
rcu_read_lock(); rcu_read_lock();
err = mesh_nexthop_lookup(skb, sdata); err = mesh_nexthop_lookup(sdata, skb);
if (!err) if (!err)
goto endlookup; goto endlookup;
/* no nexthop found, start resolving */ /* no nexthop found, start resolving */
mpath = mesh_path_lookup(target_addr, sdata); mpath = mesh_path_lookup(sdata, target_addr);
if (!mpath) { if (!mpath) {
mesh_path_add(target_addr, sdata); mesh_path_add(sdata, target_addr);
mpath = mesh_path_lookup(target_addr, sdata); mpath = mesh_path_lookup(sdata, target_addr);
if (!mpath) { if (!mpath) {
mesh_path_discard_frame(skb, sdata); mesh_path_discard_frame(sdata, skb);
err = -ENOSPC; err = -ENOSPC;
goto endlookup; goto endlookup;
} }
@ -1118,12 +1118,13 @@ int mesh_nexthop_resolve(struct sk_buff *skb,
skb_queue_tail(&mpath->frame_queue, skb); skb_queue_tail(&mpath->frame_queue, skb);
err = -ENOENT; err = -ENOENT;
if (skb_to_free) if (skb_to_free)
mesh_path_discard_frame(skb_to_free, sdata); mesh_path_discard_frame(sdata, skb_to_free);
endlookup: endlookup:
rcu_read_unlock(); rcu_read_unlock();
return err; return err;
} }
/** /**
* mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling
* this function is considered "using" the associated mpath, so preempt a path * this function is considered "using" the associated mpath, so preempt a path
@ -1134,8 +1135,8 @@ int mesh_nexthop_resolve(struct sk_buff *skb,
* *
* Returns: 0 if the next hop was found. Nonzero otherwise. * Returns: 0 if the next hop was found. Nonzero otherwise.
*/ */
int mesh_nexthop_lookup(struct sk_buff *skb, int mesh_nexthop_lookup(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata) struct sk_buff *skb)
{ {
struct mesh_path *mpath; struct mesh_path *mpath;
struct sta_info *next_hop; struct sta_info *next_hop;
@ -1144,7 +1145,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
int err = -ENOENT; int err = -ENOENT;
rcu_read_lock(); rcu_read_lock();
mpath = mesh_path_lookup(target_addr, sdata); mpath = mesh_path_lookup(sdata, target_addr);
if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE)) if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE))
goto endlookup; goto endlookup;
@ -1203,8 +1204,7 @@ void mesh_path_timer(unsigned long data)
} }
} }
void void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
{ {
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval; u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;

View File

@ -24,9 +24,12 @@
/* Keep the mean chain length below this constant */ /* Keep the mean chain length below this constant */
#define MEAN_CHAIN_LEN 2 #define MEAN_CHAIN_LEN 2
#define MPATH_EXPIRED(mpath) ((mpath->flags & MESH_PATH_ACTIVE) && \ static inline bool mpath_expired(struct mesh_path *mpath)
time_after(jiffies, mpath->exp_time) && \ {
!(mpath->flags & MESH_PATH_FIXED)) return (mpath->flags & MESH_PATH_ACTIVE) &&
time_after(jiffies, mpath->exp_time) &&
!(mpath->flags & MESH_PATH_FIXED);
}
struct mpath_node { struct mpath_node {
struct hlist_node list; struct hlist_node list;
@ -185,8 +188,8 @@ static u32 mesh_table_hash(const u8 *addr, struct ieee80211_sub_if_data *sdata,
struct mesh_table *tbl) struct mesh_table *tbl)
{ {
/* Use last four bytes of hw addr and interface index as hash index */ /* Use last four bytes of hw addr and interface index as hash index */
return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, tbl->hash_rnd) return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex,
& tbl->hash_mask; tbl->hash_rnd) & tbl->hash_mask;
} }
@ -339,7 +342,7 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst,
mpath = node->mpath; mpath = node->mpath;
if (mpath->sdata == sdata && if (mpath->sdata == sdata &&
ether_addr_equal(dst, mpath->dst)) { ether_addr_equal(dst, mpath->dst)) {
if (MPATH_EXPIRED(mpath)) { if (mpath_expired(mpath)) {
spin_lock_bh(&mpath->state_lock); spin_lock_bh(&mpath->state_lock);
mpath->flags &= ~MESH_PATH_ACTIVE; mpath->flags &= ~MESH_PATH_ACTIVE;
spin_unlock_bh(&mpath->state_lock); spin_unlock_bh(&mpath->state_lock);
@ -352,20 +355,21 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst,
/** /**
* mesh_path_lookup - look up a path in the mesh path table * mesh_path_lookup - look up a path in the mesh path table
* @dst: hardware address (ETH_ALEN length) of destination
* @sdata: local subif * @sdata: local subif
* @dst: hardware address (ETH_ALEN length) of destination
* *
* Returns: pointer to the mesh path structure, or NULL if not found * Returns: pointer to the mesh path structure, or NULL if not found
* *
* Locking: must be called within a read rcu section. * Locking: must be called within a read rcu section.
*/ */
struct mesh_path *mesh_path_lookup(const u8 *dst, struct mesh_path *
struct ieee80211_sub_if_data *sdata) mesh_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst)
{ {
return mpath_lookup(rcu_dereference(mesh_paths), dst, sdata); return mpath_lookup(rcu_dereference(mesh_paths), dst, sdata);
} }
struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) struct mesh_path *
mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst)
{ {
return mpath_lookup(rcu_dereference(mpp_paths), dst, sdata); return mpath_lookup(rcu_dereference(mpp_paths), dst, sdata);
} }
@ -380,7 +384,8 @@ struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata)
* *
* Locking: must be called within a read rcu section. * Locking: must be called within a read rcu section.
*/ */
struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data *sdata) struct mesh_path *
mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx)
{ {
struct mesh_table *tbl = rcu_dereference(mesh_paths); struct mesh_table *tbl = rcu_dereference(mesh_paths);
struct mpath_node *node; struct mpath_node *node;
@ -392,7 +397,7 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data
if (sdata && node->mpath->sdata != sdata) if (sdata && node->mpath->sdata != sdata)
continue; continue;
if (j++ == idx) { if (j++ == idx) {
if (MPATH_EXPIRED(node->mpath)) { if (mpath_expired(node->mpath)) {
spin_lock_bh(&node->mpath->state_lock); spin_lock_bh(&node->mpath->state_lock);
node->mpath->flags &= ~MESH_PATH_ACTIVE; node->mpath->flags &= ~MESH_PATH_ACTIVE;
spin_unlock_bh(&node->mpath->state_lock); spin_unlock_bh(&node->mpath->state_lock);
@ -436,11 +441,10 @@ int mesh_path_add_gate(struct mesh_path *mpath)
spin_lock_bh(&tbl->gates_lock); spin_lock_bh(&tbl->gates_lock);
hlist_add_head_rcu(&new_gate->list, tbl->known_gates); hlist_add_head_rcu(&new_gate->list, tbl->known_gates);
spin_unlock_bh(&tbl->gates_lock); spin_unlock_bh(&tbl->gates_lock);
rcu_read_unlock();
mpath_dbg(mpath->sdata, mpath_dbg(mpath->sdata,
"Mesh path: Recorded new gate: %pM. %d known gates\n", "Mesh path: Recorded new gate: %pM. %d known gates\n",
mpath->dst, mpath->sdata->u.mesh.num_gates); mpath->dst, mpath->sdata->u.mesh.num_gates);
return 0; err = 0;
err_rcu: err_rcu:
rcu_read_unlock(); rcu_read_unlock();
return err; return err;
@ -451,30 +455,27 @@ int mesh_path_add_gate(struct mesh_path *mpath)
* @tbl: table which holds our list of known gates * @tbl: table which holds our list of known gates
* @mpath: gate mpath * @mpath: gate mpath
* *
* Returns: 0 on success
*
* Locking: must be called inside rcu_read_lock() section * Locking: must be called inside rcu_read_lock() section
*/ */
static int mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath) static void mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath)
{ {
struct mpath_node *gate; struct mpath_node *gate;
struct hlist_node *p, *q; struct hlist_node *p, *q;
hlist_for_each_entry_safe(gate, p, q, tbl->known_gates, list) hlist_for_each_entry_safe(gate, p, q, tbl->known_gates, list) {
if (gate->mpath == mpath) { if (gate->mpath != mpath)
spin_lock_bh(&tbl->gates_lock); continue;
hlist_del_rcu(&gate->list); spin_lock_bh(&tbl->gates_lock);
kfree_rcu(gate, rcu); hlist_del_rcu(&gate->list);
spin_unlock_bh(&tbl->gates_lock); kfree_rcu(gate, rcu);
mpath->sdata->u.mesh.num_gates--; spin_unlock_bh(&tbl->gates_lock);
mpath->is_gate = false; mpath->sdata->u.mesh.num_gates--;
mpath_dbg(mpath->sdata, mpath->is_gate = false;
"Mesh path: Deleted gate: %pM. %d known gates\n", mpath_dbg(mpath->sdata,
mpath->dst, mpath->sdata->u.mesh.num_gates); "Mesh path: Deleted gate: %pM. %d known gates\n",
break; mpath->dst, mpath->sdata->u.mesh.num_gates);
} break;
}
return 0;
} }
/** /**
@ -488,14 +489,14 @@ int mesh_gate_num(struct ieee80211_sub_if_data *sdata)
/** /**
* mesh_path_add - allocate and add a new path to the mesh path table * mesh_path_add - allocate and add a new path to the mesh path table
* @addr: destination address of the path (ETH_ALEN length) * @dst: destination address of the path (ETH_ALEN length)
* @sdata: local subif * @sdata: local subif
* *
* Returns: 0 on success * Returns: 0 on success
* *
* State: the initial state of the new path is set to 0 * State: the initial state of the new path is set to 0
*/ */
int mesh_path_add(const u8 *dst, struct ieee80211_sub_if_data *sdata) int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
{ {
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
@ -630,7 +631,8 @@ void mesh_mpp_table_grow(void)
write_unlock_bh(&pathtbl_resize_lock); write_unlock_bh(&pathtbl_resize_lock);
} }
int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) int mpp_path_add(struct ieee80211_sub_if_data *sdata,
const u8 *dst, const u8 *mpp)
{ {
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
@ -739,9 +741,10 @@ void mesh_plink_broken(struct sta_info *sta)
mpath->flags &= ~MESH_PATH_ACTIVE; mpath->flags &= ~MESH_PATH_ACTIVE;
++mpath->sn; ++mpath->sn;
spin_unlock_bh(&mpath->state_lock); spin_unlock_bh(&mpath->state_lock);
mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, mesh_path_error_tx(sdata,
mpath->dst, cpu_to_le32(mpath->sn), sdata->u.mesh.mshcfg.element_ttl,
reason, bcast, sdata); mpath->dst, cpu_to_le32(mpath->sn),
reason, bcast);
} }
} }
rcu_read_unlock(); rcu_read_unlock();
@ -856,7 +859,7 @@ void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata)
* *
* Returns: 0 if successful * Returns: 0 if successful
*/ */
int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
{ {
struct mesh_table *tbl; struct mesh_table *tbl;
struct mesh_path *mpath; struct mesh_path *mpath;
@ -965,8 +968,8 @@ int mesh_path_send_to_gates(struct mesh_path *mpath)
* *
* Locking: the function must me called within a rcu_read_lock region * Locking: the function must me called within a rcu_read_lock region
*/ */
void mesh_path_discard_frame(struct sk_buff *skb, void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sub_if_data *sdata) struct sk_buff *skb)
{ {
kfree_skb(skb); kfree_skb(skb);
sdata->u.mesh.mshstats.dropped_frames_no_route++; sdata->u.mesh.mshstats.dropped_frames_no_route++;
@ -984,7 +987,7 @@ void mesh_path_flush_pending(struct mesh_path *mpath)
struct sk_buff *skb; struct sk_buff *skb;
while ((skb = skb_dequeue(&mpath->frame_queue)) != NULL) while ((skb = skb_dequeue(&mpath->frame_queue)) != NULL)
mesh_path_discard_frame(skb, mpath->sdata); mesh_path_discard_frame(mpath->sdata, skb);
} }
/** /**
@ -1105,7 +1108,7 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata)
if ((!(mpath->flags & MESH_PATH_RESOLVING)) && if ((!(mpath->flags & MESH_PATH_RESOLVING)) &&
(!(mpath->flags & MESH_PATH_FIXED)) && (!(mpath->flags & MESH_PATH_FIXED)) &&
time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE))
mesh_path_del(mpath->dst, mpath->sdata); mesh_path_del(mpath->sdata, mpath->dst);
} }
rcu_read_unlock(); rcu_read_unlock();
} }

View File

@ -38,8 +38,8 @@ enum plink_event {
}; };
static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
enum ieee80211_self_protected_actioncode action, enum ieee80211_self_protected_actioncode action,
u8 *da, __le16 llid, __le16 plid, __le16 reason); u8 *da, __le16 llid, __le16 plid, __le16 reason);
/** /**
* mesh_plink_fsm_restart - restart a mesh peer link finite state machine * mesh_plink_fsm_restart - restart a mesh peer link finite state machine
@ -231,8 +231,9 @@ u32 mesh_plink_deactivate(struct sta_info *sta)
} }
static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
enum ieee80211_self_protected_actioncode action, enum ieee80211_self_protected_actioncode action,
u8 *da, __le16 llid, __le16 plid, __le16 reason) { u8 *da, __le16 llid, __le16 plid, __le16 reason)
{
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct sk_buff *skb; struct sk_buff *skb;
struct ieee80211_tx_info *info; struct ieee80211_tx_info *info;
@ -283,13 +284,13 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
} }
if (ieee80211_add_srates_ie(sdata, skb, true, band) || if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
ieee80211_add_ext_srates_ie(sdata, skb, true, band) || ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
mesh_add_rsn_ie(skb, sdata) || mesh_add_rsn_ie(sdata, skb) ||
mesh_add_meshid_ie(skb, sdata) || mesh_add_meshid_ie(sdata, skb) ||
mesh_add_meshconf_ie(skb, sdata)) mesh_add_meshconf_ie(sdata, skb))
goto free; goto free;
} else { /* WLAN_SP_MESH_PEERING_CLOSE */ } else { /* WLAN_SP_MESH_PEERING_CLOSE */
info->flags |= IEEE80211_TX_CTL_NO_ACK; info->flags |= IEEE80211_TX_CTL_NO_ACK;
if (mesh_add_meshid_ie(skb, sdata)) if (mesh_add_meshid_ie(sdata, skb))
goto free; goto free;
} }
@ -333,12 +334,12 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
} }
if (action != WLAN_SP_MESH_PEERING_CLOSE) { if (action != WLAN_SP_MESH_PEERING_CLOSE) {
if (mesh_add_ht_cap_ie(skb, sdata) || if (mesh_add_ht_cap_ie(sdata, skb) ||
mesh_add_ht_oper_ie(skb, sdata)) mesh_add_ht_oper_ie(sdata, skb))
goto free; goto free;
} }
if (mesh_add_vendor_ies(skb, sdata)) if (mesh_add_vendor_ies(sdata, skb))
goto free; goto free;
ieee80211_tx_skb(sdata, skb); ieee80211_tx_skb(sdata, skb);
@ -666,8 +667,9 @@ u32 mesh_plink_block(struct sta_info *sta)
} }
void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
size_t len, struct ieee80211_rx_status *rx_status) struct ieee80211_mgmt *mgmt, size_t len,
struct ieee80211_rx_status *rx_status)
{ {
struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg;
struct ieee802_11_elems elems; struct ieee802_11_elems elems;
@ -680,7 +682,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
u8 *baseaddr; u8 *baseaddr;
u32 changed = 0; u32 changed = 0;
__le16 plid, llid, reason; __le16 plid, llid, reason;
static const char *mplstates[] = { static const char * const mplstates[] = {
[NL80211_PLINK_LISTEN] = "LISTEN", [NL80211_PLINK_LISTEN] = "LISTEN",
[NL80211_PLINK_OPN_SNT] = "OPN-SNT", [NL80211_PLINK_OPN_SNT] = "OPN-SNT",
[NL80211_PLINK_OPN_RCVD] = "OPN-RCVD", [NL80211_PLINK_OPN_RCVD] = "OPN-RCVD",
@ -708,13 +710,15 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
baselen += 4; baselen += 4;
} }
ieee802_11_parse_elems(baseaddr, len - baselen, &elems); ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
if (!elems.peering) { if (!elems.peering) {
mpl_dbg(sdata, mpl_dbg(sdata,
"Mesh plink: missing necessary peer link ie\n"); "Mesh plink: missing necessary peer link ie\n");
return; return;
} }
if (elems.rsn_len && if (elems.rsn_len &&
sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
mpl_dbg(sdata, mpl_dbg(sdata,
"Mesh plink: can't establish link with secure peer\n"); "Mesh plink: can't establish link with secure peer\n");
return; return;
@ -733,7 +737,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
} }
if (ftype != WLAN_SP_MESH_PEERING_CLOSE && if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
(!elems.mesh_id || !elems.mesh_config)) { (!elems.mesh_id || !elems.mesh_config)) {
mpl_dbg(sdata, "Mesh plink: missing necessary ie\n"); mpl_dbg(sdata, "Mesh plink: missing necessary ie\n");
return; return;
} }

View File

@ -43,7 +43,7 @@ struct sync_method {
static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie) static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie)
{ {
return (ie->mesh_config->meshconf_cap & return (ie->mesh_config->meshconf_cap &
IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING) != 0; IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING) != 0;
} }
void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata) void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
@ -112,7 +112,8 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
if (elems->mesh_config && mesh_peer_tbtt_adjusting(elems)) { if (elems->mesh_config && mesh_peer_tbtt_adjusting(elems)) {
clear_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); clear_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN);
msync_dbg(sdata, "STA %pM : is adjusting TBTT\n", sta->sta.addr); msync_dbg(sdata, "STA %pM : is adjusting TBTT\n",
sta->sta.addr);
goto no_sync; goto no_sync;
} }
@ -129,18 +130,15 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
sta->t_offset = t_t - t_r; sta->t_offset = t_t - t_r;
if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) {
s64 t_clockdrift = sta->t_offset_setpoint s64 t_clockdrift = sta->t_offset_setpoint - sta->t_offset;
- sta->t_offset;
msync_dbg(sdata, msync_dbg(sdata,
"STA %pM : sta->t_offset=%lld, sta->t_offset_setpoint=%lld, t_clockdrift=%lld\n", "STA %pM : sta->t_offset=%lld, sta->t_offset_setpoint=%lld, t_clockdrift=%lld\n",
sta->sta.addr, sta->sta.addr, (long long) sta->t_offset,
(long long) sta->t_offset, (long long) sta->t_offset_setpoint,
(long long)
sta->t_offset_setpoint,
(long long) t_clockdrift); (long long) t_clockdrift);
if (t_clockdrift > TOFFSET_MAXIMUM_ADJUSTMENT || if (t_clockdrift > TOFFSET_MAXIMUM_ADJUSTMENT ||
t_clockdrift < -TOFFSET_MAXIMUM_ADJUSTMENT) { t_clockdrift < -TOFFSET_MAXIMUM_ADJUSTMENT) {
msync_dbg(sdata, msync_dbg(sdata,
"STA %pM : t_clockdrift=%lld too large, setpoint reset\n", "STA %pM : t_clockdrift=%lld too large, setpoint reset\n",
sta->sta.addr, sta->sta.addr,
@ -149,15 +147,10 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
goto no_sync; goto no_sync;
} }
rcu_read_unlock();
spin_lock_bh(&ifmsh->sync_offset_lock); spin_lock_bh(&ifmsh->sync_offset_lock);
if (t_clockdrift > if (t_clockdrift > ifmsh->sync_offset_clockdrift_max)
ifmsh->sync_offset_clockdrift_max) ifmsh->sync_offset_clockdrift_max = t_clockdrift;
ifmsh->sync_offset_clockdrift_max
= t_clockdrift;
spin_unlock_bh(&ifmsh->sync_offset_lock); spin_unlock_bh(&ifmsh->sync_offset_lock);
} else { } else {
sta->t_offset_setpoint = sta->t_offset - TOFFSET_SET_MARGIN; sta->t_offset_setpoint = sta->t_offset - TOFFSET_SET_MARGIN;
set_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); set_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN);
@ -165,9 +158,7 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
"STA %pM : offset was invalid, sta->t_offset=%lld\n", "STA %pM : offset was invalid, sta->t_offset=%lld\n",
sta->sta.addr, sta->sta.addr,
(long long) sta->t_offset); (long long) sta->t_offset);
rcu_read_unlock();
} }
return;
no_sync: no_sync:
rcu_read_unlock(); rcu_read_unlock();
@ -177,14 +168,12 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
{ {
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
WARN_ON(ifmsh->mesh_sp_id WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET);
!= IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET);
BUG_ON(!rcu_read_lock_held()); BUG_ON(!rcu_read_lock_held());
spin_lock_bh(&ifmsh->sync_offset_lock); spin_lock_bh(&ifmsh->sync_offset_lock);
if (ifmsh->sync_offset_clockdrift_max > if (ifmsh->sync_offset_clockdrift_max > TOFFSET_MINIMUM_ADJUSTMENT) {
TOFFSET_MINIMUM_ADJUSTMENT) {
/* Since ajusting the tsf here would /* Since ajusting the tsf here would
* require a possibly blocking call * require a possibly blocking call
* to the driver tsf setter, we punt * to the driver tsf setter, we punt
@ -193,8 +182,7 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
msync_dbg(sdata, msync_dbg(sdata,
"TBTT : kicking off TBTT adjustment with clockdrift_max=%lld\n", "TBTT : kicking off TBTT adjustment with clockdrift_max=%lld\n",
ifmsh->sync_offset_clockdrift_max); ifmsh->sync_offset_clockdrift_max);
set_bit(MESH_WORK_DRIFT_ADJUST, set_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags);
&ifmsh->wrkq_flags);
ifmsh->adjusting_tbtt = true; ifmsh->adjusting_tbtt = true;
} else { } else {
@ -220,14 +208,11 @@ static const struct sync_method sync_methods[] = {
const struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method) const struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method)
{ {
const struct ieee80211_mesh_sync_ops *ops = NULL; int i;
u8 i;
for (i = 0 ; i < ARRAY_SIZE(sync_methods); ++i) { for (i = 0 ; i < ARRAY_SIZE(sync_methods); ++i) {
if (sync_methods[i].method == method) { if (sync_methods[i].method == method)
ops = &sync_methods[i].ops; return &sync_methods[i].ops;
break;
}
} }
return ops; return NULL;
} }

View File

@ -2027,7 +2027,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
/* frame is in RMC, don't forward */ /* frame is in RMC, don't forward */
if (ieee80211_is_data(hdr->frame_control) && if (ieee80211_is_data(hdr->frame_control) &&
is_multicast_ether_addr(hdr->addr1) && is_multicast_ether_addr(hdr->addr1) &&
mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) mesh_rmc_check(rx->sdata, hdr->addr3, mesh_hdr))
return RX_DROP_MONITOR; return RX_DROP_MONITOR;
if (!ieee80211_is_data(hdr->frame_control) || if (!ieee80211_is_data(hdr->frame_control) ||
@ -2054,9 +2054,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
} }
rcu_read_lock(); rcu_read_lock();
mppath = mpp_path_lookup(proxied_addr, sdata); mppath = mpp_path_lookup(sdata, proxied_addr);
if (!mppath) { if (!mppath) {
mpp_path_add(proxied_addr, mpp_addr, sdata); mpp_path_add(sdata, proxied_addr, mpp_addr);
} else { } else {
spin_lock_bh(&mppath->state_lock); spin_lock_bh(&mppath->state_lock);
if (!ether_addr_equal(mppath->mpp, mpp_addr)) if (!ether_addr_equal(mppath->mpp, mpp_addr))
@ -2104,13 +2104,13 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
/* update power mode indication when forwarding */ /* update power mode indication when forwarding */
ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr); ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr);
} else if (!mesh_nexthop_lookup(fwd_skb, sdata)) { } else if (!mesh_nexthop_lookup(sdata, fwd_skb)) {
/* mesh power mode flags updated in mesh_nexthop_lookup */ /* mesh power mode flags updated in mesh_nexthop_lookup */
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast); IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
} else { } else {
/* unable to resolve next hop */ /* unable to resolve next hop */
mesh_path_error_tx(ifmsh->mshcfg.element_ttl, fwd_hdr->addr3, mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl,
0, reason, fwd_hdr->addr2, sdata); fwd_hdr->addr3, 0, reason, fwd_hdr->addr2);
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route); IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route);
kfree_skb(fwd_skb); kfree_skb(fwd_skb);
return RX_DROP_MONITOR; return RX_DROP_MONITOR;

View File

@ -1495,7 +1495,7 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
if (ieee80211_vif_is_mesh(&sdata->vif)) { if (ieee80211_vif_is_mesh(&sdata->vif)) {
if (ieee80211_is_data(hdr->frame_control) && if (ieee80211_is_data(hdr->frame_control) &&
is_unicast_ether_addr(hdr->addr1)) { is_unicast_ether_addr(hdr->addr1)) {
if (mesh_nexthop_resolve(skb, sdata)) if (mesh_nexthop_resolve(sdata, skb))
return; /* skb queued: don't free */ return; /* skb queued: don't free */
} else { } else {
ieee80211_mps_set_frame_flags(sdata, NULL, hdr); ieee80211_mps_set_frame_flags(sdata, NULL, hdr);
@ -1844,9 +1844,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
} }
if (!is_multicast_ether_addr(skb->data)) { if (!is_multicast_ether_addr(skb->data)) {
mpath = mesh_path_lookup(skb->data, sdata); mpath = mesh_path_lookup(sdata, skb->data);
if (!mpath) if (!mpath)
mppath = mpp_path_lookup(skb->data, sdata); mppath = mpp_path_lookup(sdata, skb->data);
} }
/* /*
@ -1859,8 +1859,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
!(mppath && !ether_addr_equal(mppath->mpp, skb->data))) { !(mppath && !ether_addr_equal(mppath->mpp, skb->data))) {
hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
skb->data, skb->data + ETH_ALEN); skb->data, skb->data + ETH_ALEN);
meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, meshhdrlen = ieee80211_new_mesh_header(sdata, &mesh_hdr,
sdata, NULL, NULL); NULL, NULL);
} else { } else {
/* DS -> MBSS (802.11-2012 13.11.3.3). /* DS -> MBSS (802.11-2012 13.11.3.3).
* For unicast with unknown forwarding information, * For unicast with unknown forwarding information,
@ -1879,18 +1879,14 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
mesh_da, sdata->vif.addr); mesh_da, sdata->vif.addr);
if (is_multicast_ether_addr(mesh_da)) if (is_multicast_ether_addr(mesh_da))
/* DA TA mSA AE:SA */ /* DA TA mSA AE:SA */
meshhdrlen = meshhdrlen = ieee80211_new_mesh_header(
ieee80211_new_mesh_header(&mesh_hdr, sdata, &mesh_hdr,
sdata, skb->data + ETH_ALEN, NULL);
skb->data + ETH_ALEN,
NULL);
else else
/* RA TA mDA mSA AE:DA SA */ /* RA TA mDA mSA AE:DA SA */
meshhdrlen = meshhdrlen = ieee80211_new_mesh_header(
ieee80211_new_mesh_header(&mesh_hdr, sdata, &mesh_hdr, skb->data,
sdata, skb->data + ETH_ALEN);
skb->data,
skb->data + ETH_ALEN);
} }
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);