diff options
| -rw-r--r-- | Documentation/DocBook/80211.tmpl | 4 | ||||
| -rw-r--r-- | net/mac80211/cfg.c | 14 | ||||
| -rw-r--r-- | net/mac80211/iface.c | 8 | ||||
| -rw-r--r-- | net/mac80211/main.c | 3 | ||||
| -rw-r--r-- | net/mac80211/mesh.c | 116 | ||||
| -rw-r--r-- | net/mac80211/mesh.h | 105 | ||||
| -rw-r--r-- | net/mac80211/mesh_hwmp.c | 68 | ||||
| -rw-r--r-- | net/mac80211/mesh_pathtbl.c | 89 | ||||
| -rw-r--r-- | net/mac80211/mesh_plink.c | 134 | ||||
| -rw-r--r-- | net/mac80211/mesh_sync.c | 47 | ||||
| -rw-r--r-- | net/mac80211/rx.c | 12 | ||||
| -rw-r--r-- | net/mac80211/sta_info.h | 2 | ||||
| -rw-r--r-- | net/mac80211/trace.h | 6 | ||||
| -rw-r--r-- | net/mac80211/tx.c | 26 | ||||
| -rw-r--r-- | net/wireless/nl80211.c | 9 |
15 files changed, 309 insertions, 334 deletions
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index 42e7f030cb16..284ced7a228f 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl | |||
| @@ -107,8 +107,8 @@ | |||
| 107 | !Finclude/net/cfg80211.h key_params | 107 | !Finclude/net/cfg80211.h key_params |
| 108 | !Finclude/net/cfg80211.h survey_info_flags | 108 | !Finclude/net/cfg80211.h survey_info_flags |
| 109 | !Finclude/net/cfg80211.h survey_info | 109 | !Finclude/net/cfg80211.h survey_info |
| 110 | !Finclude/net/cfg80211.h beacon_parameters | 110 | !Finclude/net/cfg80211.h cfg80211_beacon_data |
| 111 | !Finclude/net/cfg80211.h plink_actions | 111 | !Finclude/net/cfg80211.h cfg80211_ap_settings |
| 112 | !Finclude/net/cfg80211.h station_parameters | 112 | !Finclude/net/cfg80211.h station_parameters |
| 113 | !Finclude/net/cfg80211.h station_info_flags | 113 | !Finclude/net/cfg80211.h station_info_flags |
| 114 | !Finclude/net/cfg80211.h rate_info_flags | 114 | !Finclude/net/cfg80211.h rate_info_flags |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 179dcbd8be1c..09d96a8f6c2c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
| @@ -1500,13 +1500,13 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
| 1500 | return -ENOENT; | 1500 | return -ENOENT; |
| 1501 | } | 1501 | } |
| 1502 | 1502 | ||
| 1503 | err = mesh_path_add(dst, sdata); | 1503 | err = mesh_path_add(sdata, dst); |
| 1504 | if (err) { | 1504 | if (err) { |
| 1505 | rcu_read_unlock(); | 1505 | rcu_read_unlock(); |
| 1506 | return err; | 1506 | return err; |
| 1507 | } | 1507 | } |
| 1508 | 1508 | ||
| 1509 | mpath = mesh_path_lookup(dst, sdata); | 1509 | mpath = mesh_path_lookup(sdata, dst); |
| 1510 | if (!mpath) { | 1510 | if (!mpath) { |
| 1511 | rcu_read_unlock(); | 1511 | rcu_read_unlock(); |
| 1512 | return -ENXIO; | 1512 | return -ENXIO; |
| @@ -1518,12 +1518,12 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
| 1518 | } | 1518 | } |
| 1519 | 1519 | ||
| 1520 | static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, | 1520 | static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, |
| 1521 | u8 *dst) | 1521 | u8 *dst) |
| 1522 | { | 1522 | { |
| 1523 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1523 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 1524 | 1524 | ||
| 1525 | if (dst) | 1525 | if (dst) |
| 1526 | return mesh_path_del(dst, sdata); | 1526 | return mesh_path_del(sdata, dst); |
| 1527 | 1527 | ||
| 1528 | mesh_path_flush_by_iface(sdata); | 1528 | mesh_path_flush_by_iface(sdata); |
| 1529 | return 0; | 1529 | return 0; |
| @@ -1547,7 +1547,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
| 1547 | return -ENOENT; | 1547 | return -ENOENT; |
| 1548 | } | 1548 | } |
| 1549 | 1549 | ||
| 1550 | mpath = mesh_path_lookup(dst, sdata); | 1550 | mpath = mesh_path_lookup(sdata, dst); |
| 1551 | if (!mpath) { | 1551 | if (!mpath) { |
| 1552 | rcu_read_unlock(); | 1552 | rcu_read_unlock(); |
| 1553 | return -ENOENT; | 1553 | return -ENOENT; |
| @@ -1611,7 +1611,7 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
| 1611 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1611 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 1612 | 1612 | ||
| 1613 | rcu_read_lock(); | 1613 | rcu_read_lock(); |
| 1614 | mpath = mesh_path_lookup(dst, sdata); | 1614 | mpath = mesh_path_lookup(sdata, dst); |
| 1615 | if (!mpath) { | 1615 | if (!mpath) { |
| 1616 | rcu_read_unlock(); | 1616 | rcu_read_unlock(); |
| 1617 | return -ENOENT; | 1617 | return -ENOENT; |
| @@ -1632,7 +1632,7 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
| 1632 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1632 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 1633 | 1633 | ||
| 1634 | rcu_read_lock(); | 1634 | rcu_read_lock(); |
| 1635 | mpath = mesh_path_lookup_by_idx(idx, sdata); | 1635 | mpath = mesh_path_lookup_by_idx(sdata, idx); |
| 1636 | if (!mpath) { | 1636 | if (!mpath) { |
| 1637 | rcu_read_unlock(); | 1637 | rcu_read_unlock(); |
| 1638 | return -ENOENT; | 1638 | return -ENOENT; |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 86c83084542a..2c059e54e885 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
| @@ -294,7 +294,8 @@ static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata) | |||
| 294 | } | 294 | } |
| 295 | } | 295 | } |
| 296 | 296 | ||
| 297 | if ((sdata->vif.type != NL80211_IFTYPE_AP) || | 297 | if ((sdata->vif.type != NL80211_IFTYPE_AP && |
| 298 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT) || | ||
| 298 | !(sdata->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)) { | 299 | !(sdata->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)) { |
| 299 | sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; | 300 | sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; |
| 300 | return 0; | 301 | return 0; |
| @@ -695,6 +696,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
| 695 | 696 | ||
| 696 | ieee80211_roc_purge(sdata); | 697 | ieee80211_roc_purge(sdata); |
| 697 | 698 | ||
| 699 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
| 700 | ieee80211_mgd_stop(sdata); | ||
| 701 | |||
| 698 | /* | 702 | /* |
| 699 | * Remove all stations associated with this interface. | 703 | * Remove all stations associated with this interface. |
| 700 | * | 704 | * |
| @@ -782,8 +786,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
| 782 | } | 786 | } |
| 783 | } | 787 | } |
| 784 | spin_unlock_irqrestore(&ps->bc_buf.lock, flags); | 788 | spin_unlock_irqrestore(&ps->bc_buf.lock, flags); |
| 785 | } else if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
| 786 | ieee80211_mgd_stop(sdata); | ||
| 787 | } | 789 | } |
| 788 | 790 | ||
| 789 | if (going_down) | 791 | if (going_down) |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index f9747689d604..d0dd11153a6c 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
| @@ -1173,8 +1173,7 @@ static void __exit ieee80211_exit(void) | |||
| 1173 | rc80211_minstrel_ht_exit(); | 1173 | rc80211_minstrel_ht_exit(); |
| 1174 | rc80211_minstrel_exit(); | 1174 | rc80211_minstrel_exit(); |
| 1175 | 1175 | ||
| 1176 | if (mesh_allocated) | 1176 | ieee80211s_stop(); |
| 1177 | ieee80211s_stop(); | ||
| 1178 | 1177 | ||
| 1179 | ieee80211_iface_exit(); | 1178 | ieee80211_iface_exit(); |
| 1180 | 1179 | ||
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index a77d40ed4e61..29ce2aa87e7b 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | #define TMR_RUNNING_MP 1 | 17 | #define TMR_RUNNING_MP 1 |
| 18 | #define TMR_RUNNING_MPR 2 | 18 | #define TMR_RUNNING_MPR 2 |
| 19 | 19 | ||
| 20 | int mesh_allocated; | 20 | static int mesh_allocated; |
| 21 | static struct kmem_cache *rm_cache; | 21 | static struct kmem_cache *rm_cache; |
| 22 | 22 | ||
| 23 | bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) | 23 | bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) |
| @@ -36,6 +36,8 @@ void ieee80211s_init(void) | |||
| 36 | 36 | ||
| 37 | void ieee80211s_stop(void) | 37 | void ieee80211s_stop(void) |
| 38 | { | 38 | { |
| 39 | if (!mesh_allocated) | ||
| 40 | return; | ||
| 39 | mesh_pathtbl_unregister(); | 41 | mesh_pathtbl_unregister(); |
| 40 | kmem_cache_destroy(rm_cache); | 42 | kmem_cache_destroy(rm_cache); |
| 41 | } | 43 | } |
| @@ -90,24 +92,22 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | |||
| 90 | (ifmsh->mesh_cc_id == ie->mesh_config->meshconf_congest) && | 92 | (ifmsh->mesh_cc_id == ie->mesh_config->meshconf_congest) && |
| 91 | (ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) && | 93 | (ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) && |
| 92 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) | 94 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) |
| 93 | goto mismatch; | 95 | return false; |
| 94 | 96 | ||
| 95 | ieee80211_sta_get_rates(local, ie, ieee80211_get_sdata_band(sdata), | 97 | ieee80211_sta_get_rates(local, ie, ieee80211_get_sdata_band(sdata), |
| 96 | &basic_rates); | 98 | &basic_rates); |
| 97 | 99 | ||
| 98 | if (sdata->vif.bss_conf.basic_rates != basic_rates) | 100 | if (sdata->vif.bss_conf.basic_rates != basic_rates) |
| 99 | goto mismatch; | 101 | return false; |
| 100 | 102 | ||
| 101 | ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, | 103 | ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, |
| 102 | ie->ht_operation, &sta_chan_def); | 104 | ie->ht_operation, &sta_chan_def); |
| 103 | 105 | ||
| 104 | if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef, | 106 | if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef, |
| 105 | &sta_chan_def)) | 107 | &sta_chan_def)) |
| 106 | goto mismatch; | 108 | return false; |
| 107 | 109 | ||
| 108 | return true; | 110 | return true; |
| 109 | mismatch: | ||
| 110 | return false; | ||
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | /** | 113 | /** |
| @@ -118,7 +118,7 @@ mismatch: | |||
| 118 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) | 118 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) |
| 119 | { | 119 | { |
| 120 | return (ie->mesh_config->meshconf_cap & | 120 | return (ie->mesh_config->meshconf_cap & |
| 121 | IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS) != 0; | 121 | IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS) != 0; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | /** | 124 | /** |
| @@ -196,11 +196,12 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) | |||
| 196 | if (!sdata->u.mesh.rmc) | 196 | if (!sdata->u.mesh.rmc) |
| 197 | return; | 197 | return; |
| 198 | 198 | ||
| 199 | for (i = 0; i < RMC_BUCKETS; i++) | 199 | for (i = 0; i < RMC_BUCKETS; i++) { |
| 200 | list_for_each_entry_safe(p, n, &rmc->bucket[i], list) { | 200 | list_for_each_entry_safe(p, n, &rmc->bucket[i], list) { |
| 201 | list_del(&p->list); | 201 | list_del(&p->list); |
| 202 | kmem_cache_free(rm_cache, p); | 202 | kmem_cache_free(rm_cache, p); |
| 203 | } | 203 | } |
| 204 | } | ||
| 204 | 205 | ||
| 205 | kfree(rmc); | 206 | kfree(rmc); |
| 206 | sdata->u.mesh.rmc = NULL; | 207 | sdata->u.mesh.rmc = NULL; |
| @@ -209,6 +210,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) | |||
| 209 | /** | 210 | /** |
| 210 | * mesh_rmc_check - Check frame in recent multicast cache and add if absent. | 211 | * mesh_rmc_check - Check frame in recent multicast cache and add if absent. |
| 211 | * | 212 | * |
| 213 | * @sdata: interface | ||
| 212 | * @sa: source address | 214 | * @sa: source address |
| 213 | * @mesh_hdr: mesh_header | 215 | * @mesh_hdr: mesh_header |
| 214 | * | 216 | * |
| @@ -218,8 +220,8 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) | |||
| 218 | * received this frame lately. If the frame is not in the cache, it is added to | 220 | * received this frame lately. If the frame is not in the cache, it is added to |
| 219 | * it. | 221 | * it. |
| 220 | */ | 222 | */ |
| 221 | int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | 223 | int mesh_rmc_check(struct ieee80211_sub_if_data *sdata, |
| 222 | struct ieee80211_sub_if_data *sdata) | 224 | const u8 *sa, struct ieee80211s_hdr *mesh_hdr) |
| 223 | { | 225 | { |
| 224 | struct mesh_rmc *rmc = sdata->u.mesh.rmc; | 226 | struct mesh_rmc *rmc = sdata->u.mesh.rmc; |
| 225 | u32 seqnum = 0; | 227 | u32 seqnum = 0; |
| @@ -233,12 +235,11 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | |||
| 233 | list_for_each_entry_safe(p, n, &rmc->bucket[idx], list) { | 235 | list_for_each_entry_safe(p, n, &rmc->bucket[idx], list) { |
| 234 | ++entries; | 236 | ++entries; |
| 235 | if (time_after(jiffies, p->exp_time) || | 237 | if (time_after(jiffies, p->exp_time) || |
| 236 | (entries == RMC_QUEUE_MAX_LEN)) { | 238 | entries == RMC_QUEUE_MAX_LEN) { |
| 237 | list_del(&p->list); | 239 | list_del(&p->list); |
| 238 | kmem_cache_free(rm_cache, p); | 240 | kmem_cache_free(rm_cache, p); |
| 239 | --entries; | 241 | --entries; |
| 240 | } else if ((seqnum == p->seqnum) && | 242 | } else if ((seqnum == p->seqnum) && ether_addr_equal(sa, p->sa)) |
| 241 | (ether_addr_equal(sa, p->sa))) | ||
| 242 | return -1; | 243 | return -1; |
| 243 | } | 244 | } |
| 244 | 245 | ||
| @@ -253,8 +254,8 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | |||
| 253 | return 0; | 254 | return 0; |
| 254 | } | 255 | } |
| 255 | 256 | ||
| 256 | int | 257 | int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, |
| 257 | mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | 258 | struct sk_buff *skb) |
| 258 | { | 259 | { |
| 259 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 260 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
| 260 | u8 *pos, neighbors; | 261 | u8 *pos, neighbors; |
| @@ -285,19 +286,18 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
| 285 | /* Mesh capability */ | 286 | /* Mesh capability */ |
| 286 | *pos = IEEE80211_MESHCONF_CAPAB_FORWARDING; | 287 | *pos = IEEE80211_MESHCONF_CAPAB_FORWARDING; |
| 287 | *pos |= ifmsh->accepting_plinks ? | 288 | *pos |= ifmsh->accepting_plinks ? |
| 288 | IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; | 289 | IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; |
| 289 | /* Mesh PS mode. See IEEE802.11-2012 8.4.2.100.8 */ | 290 | /* Mesh PS mode. See IEEE802.11-2012 8.4.2.100.8 */ |
| 290 | *pos |= ifmsh->ps_peers_deep_sleep ? | 291 | *pos |= ifmsh->ps_peers_deep_sleep ? |
| 291 | IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL : 0x00; | 292 | IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL : 0x00; |
| 292 | *pos++ |= ifmsh->adjusting_tbtt ? | 293 | *pos++ |= ifmsh->adjusting_tbtt ? |
| 293 | IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; | 294 | IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; |
| 294 | *pos++ = 0x00; | 295 | *pos++ = 0x00; |
| 295 | 296 | ||
| 296 | return 0; | 297 | return 0; |
| 297 | } | 298 | } |
| 298 | 299 | ||
| 299 | int | 300 | int mesh_add_meshid_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) |
| 300 | mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | ||
| 301 | { | 301 | { |
| 302 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 302 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
| 303 | u8 *pos; | 303 | u8 *pos; |
| @@ -314,8 +314,8 @@ mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
| 314 | return 0; | 314 | return 0; |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | int mesh_add_awake_window_ie(struct sk_buff *skb, | 317 | static int mesh_add_awake_window_ie(struct ieee80211_sub_if_data *sdata, |
| 318 | struct ieee80211_sub_if_data *sdata) | 318 | struct sk_buff *skb) |
| 319 | { | 319 | { |
| 320 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 320 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
| 321 | u8 *pos; | 321 | u8 *pos; |
| @@ -337,8 +337,8 @@ int mesh_add_awake_window_ie(struct sk_buff *skb, | |||
| 337 | return 0; | 337 | return 0; |
| 338 | } | 338 | } |
| 339 | 339 | ||
| 340 | int | 340 | int mesh_add_vendor_ies(struct ieee80211_sub_if_data *sdata, |
| 341 | mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | 341 | struct sk_buff *skb) |
| 342 | { | 342 | { |
| 343 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 343 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
| 344 | u8 offset, len; | 344 | u8 offset, len; |
| @@ -361,8 +361,7 @@ mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
| 361 | return 0; | 361 | return 0; |
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | int | 364 | int mesh_add_rsn_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) |
| 365 | mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | ||
| 366 | { | 365 | { |
| 367 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 366 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
| 368 | u8 len = 0; | 367 | u8 len = 0; |
| @@ -390,8 +389,8 @@ mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
| 390 | return 0; | 389 | return 0; |
| 391 | } | 390 | } |
| 392 | 391 | ||
| 393 | int mesh_add_ds_params_ie(struct sk_buff *skb, | 392 | static int mesh_add_ds_params_ie(struct ieee80211_sub_if_data *sdata, |
| 394 | struct ieee80211_sub_if_data *sdata) | 393 | struct sk_buff *skb) |
| 395 | { | 394 | { |
| 396 | struct ieee80211_chanctx_conf *chanctx_conf; | 395 | struct ieee80211_chanctx_conf *chanctx_conf; |
| 397 | struct ieee80211_channel *chan; | 396 | struct ieee80211_channel *chan; |
| @@ -417,8 +416,8 @@ int mesh_add_ds_params_ie(struct sk_buff *skb, | |||
| 417 | return 0; | 416 | return 0; |
| 418 | } | 417 | } |
| 419 | 418 | ||
| 420 | int mesh_add_ht_cap_ie(struct sk_buff *skb, | 419 | int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata, |
| 421 | struct ieee80211_sub_if_data *sdata) | 420 | struct sk_buff *skb) |
| 422 | { | 421 | { |
| 423 | struct ieee80211_local *local = sdata->local; | 422 | struct ieee80211_local *local = sdata->local; |
| 424 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | 423 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); |
| @@ -439,8 +438,8 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb, | |||
| 439 | return 0; | 438 | return 0; |
| 440 | } | 439 | } |
| 441 | 440 | ||
| 442 | int mesh_add_ht_oper_ie(struct sk_buff *skb, | 441 | int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata, |
| 443 | struct ieee80211_sub_if_data *sdata) | 442 | struct sk_buff *skb) |
| 444 | { | 443 | { |
| 445 | struct ieee80211_local *local = sdata->local; | 444 | struct ieee80211_local *local = sdata->local; |
| 446 | struct ieee80211_chanctx_conf *chanctx_conf; | 445 | struct ieee80211_chanctx_conf *chanctx_conf; |
| @@ -475,6 +474,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb, | |||
| 475 | 474 | ||
| 476 | return 0; | 475 | return 0; |
| 477 | } | 476 | } |
| 477 | |||
| 478 | static void ieee80211_mesh_path_timer(unsigned long data) | 478 | static void ieee80211_mesh_path_timer(unsigned long data) |
| 479 | { | 479 | { |
| 480 | struct ieee80211_sub_if_data *sdata = | 480 | struct ieee80211_sub_if_data *sdata = |
| @@ -520,7 +520,7 @@ void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh) | |||
| 520 | 520 | ||
| 521 | /** | 521 | /** |
| 522 | * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame | 522 | * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame |
| 523 | * @hdr: 802.11 frame header | 523 | * @hdr: 802.11 frame header |
| 524 | * @fc: frame control field | 524 | * @fc: frame control field |
| 525 | * @meshda: destination address in the mesh | 525 | * @meshda: destination address in the mesh |
| 526 | * @meshsa: source address address in the mesh. Same as TA, as frame is | 526 | * @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, | |||
| 551 | 551 | ||
| 552 | /** | 552 | /** |
| 553 | * ieee80211_new_mesh_header - create a new mesh header | 553 | * ieee80211_new_mesh_header - create a new mesh header |
| 554 | * @meshhdr: uninitialized mesh header | ||
| 555 | * @sdata: mesh interface to be used | 554 | * @sdata: mesh interface to be used |
| 555 | * @meshhdr: uninitialized mesh header | ||
| 556 | * @addr4or5: 1st address in the ae header, which may correspond to address 4 | 556 | * @addr4or5: 1st address in the ae header, which may correspond to address 4 |
| 557 | * (if addr6 is NULL) or address 5 (if addr6 is present). It may | 557 | * (if addr6 is NULL) or address 5 (if addr6 is present). It may |
| 558 | * be NULL. | 558 | * be NULL. |
| @@ -561,32 +561,38 @@ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | |||
| 561 | * | 561 | * |
| 562 | * Return the header length. | 562 | * Return the header length. |
| 563 | */ | 563 | */ |
| 564 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | 564 | int ieee80211_new_mesh_header(struct ieee80211_sub_if_data *sdata, |
| 565 | struct ieee80211_sub_if_data *sdata, char *addr4or5, | 565 | struct ieee80211s_hdr *meshhdr, |
| 566 | char *addr6) | 566 | const char *addr4or5, const char *addr6) |
| 567 | { | 567 | { |
| 568 | int aelen = 0; | 568 | if (WARN_ON(!addr4or5 && addr6)) |
| 569 | BUG_ON(!addr4or5 && addr6); | 569 | return 0; |
| 570 | |||
| 570 | memset(meshhdr, 0, sizeof(*meshhdr)); | 571 | memset(meshhdr, 0, sizeof(*meshhdr)); |
| 572 | |||
| 571 | meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; | 573 | meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; |
| 574 | |||
| 575 | /* FIXME: racy -- TX on multiple queues can be concurrent */ | ||
| 572 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); | 576 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); |
| 573 | sdata->u.mesh.mesh_seqnum++; | 577 | sdata->u.mesh.mesh_seqnum++; |
| 578 | |||
| 574 | if (addr4or5 && !addr6) { | 579 | if (addr4or5 && !addr6) { |
| 575 | meshhdr->flags |= MESH_FLAGS_AE_A4; | 580 | meshhdr->flags |= MESH_FLAGS_AE_A4; |
| 576 | aelen += ETH_ALEN; | ||
| 577 | memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); | 581 | memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); |
| 582 | return 2 * ETH_ALEN; | ||
| 578 | } else if (addr4or5 && addr6) { | 583 | } else if (addr4or5 && addr6) { |
| 579 | meshhdr->flags |= MESH_FLAGS_AE_A5_A6; | 584 | meshhdr->flags |= MESH_FLAGS_AE_A5_A6; |
| 580 | aelen += 2 * ETH_ALEN; | ||
| 581 | memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); | 585 | memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); |
| 582 | memcpy(meshhdr->eaddr2, addr6, ETH_ALEN); | 586 | memcpy(meshhdr->eaddr2, addr6, ETH_ALEN); |
| 587 | return 3 * ETH_ALEN; | ||
| 583 | } | 588 | } |
| 584 | return 6 + aelen; | 589 | |
| 590 | return ETH_ALEN; | ||
| 585 | } | 591 | } |
| 586 | 592 | ||
| 587 | static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | 593 | static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata) |
| 588 | struct ieee80211_if_mesh *ifmsh) | ||
| 589 | { | 594 | { |
| 595 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
| 590 | u32 changed; | 596 | u32 changed; |
| 591 | 597 | ||
| 592 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); | 598 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); |
| @@ -596,7 +602,8 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | |||
| 596 | ieee80211_mbss_info_change_notify(sdata, changed); | 602 | ieee80211_mbss_info_change_notify(sdata, changed); |
| 597 | 603 | ||
| 598 | mod_timer(&ifmsh->housekeeping_timer, | 604 | mod_timer(&ifmsh->housekeeping_timer, |
| 599 | round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); | 605 | round_jiffies(jiffies + |
| 606 | IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); | ||
| 600 | } | 607 | } |
| 601 | 608 | ||
| 602 | static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata) | 609 | static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata) |
| @@ -708,7 +715,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
| 708 | *pos++ = 0x0; | 715 | *pos++ = 0x0; |
| 709 | 716 | ||
| 710 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || | 717 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || |
| 711 | mesh_add_ds_params_ie(skb, sdata)) | 718 | mesh_add_ds_params_ie(sdata, skb)) |
| 712 | goto out_free; | 719 | goto out_free; |
| 713 | 720 | ||
| 714 | bcn->head_len = skb->len; | 721 | bcn->head_len = skb->len; |
| @@ -719,13 +726,13 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
| 719 | bcn->tail = bcn->head + bcn->head_len; | 726 | bcn->tail = bcn->head + bcn->head_len; |
| 720 | 727 | ||
| 721 | if (ieee80211_add_ext_srates_ie(sdata, skb, true, band) || | 728 | if (ieee80211_add_ext_srates_ie(sdata, skb, true, band) || |
| 722 | mesh_add_rsn_ie(skb, sdata) || | 729 | mesh_add_rsn_ie(sdata, skb) || |
| 723 | mesh_add_ht_cap_ie(skb, sdata) || | 730 | mesh_add_ht_cap_ie(sdata, skb) || |
| 724 | mesh_add_ht_oper_ie(skb, sdata) || | 731 | mesh_add_ht_oper_ie(sdata, skb) || |
| 725 | mesh_add_meshid_ie(skb, sdata) || | 732 | mesh_add_meshid_ie(sdata, skb) || |
| 726 | mesh_add_meshconf_ie(skb, sdata) || | 733 | mesh_add_meshconf_ie(sdata, skb) || |
| 727 | mesh_add_awake_window_ie(skb, sdata) || | 734 | mesh_add_awake_window_ie(sdata, skb) || |
| 728 | mesh_add_vendor_ies(skb, sdata)) | 735 | mesh_add_vendor_ies(sdata, skb)) |
| 729 | goto out_free; | 736 | goto out_free; |
| 730 | 737 | ||
| 731 | bcn->tail_len = skb->len; | 738 | bcn->tail_len = skb->len; |
| @@ -918,7 +925,6 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata, | |||
| 918 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 925 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
| 919 | IEEE80211_STYPE_PROBE_RESP); | 926 | IEEE80211_STYPE_PROBE_RESP); |
| 920 | memcpy(hdr->da, mgmt->sa, ETH_ALEN); | 927 | memcpy(hdr->da, mgmt->sa, ETH_ALEN); |
| 921 | mpl_dbg(sdata, "sending probe resp. to %pM\n", hdr->da); | ||
| 922 | IEEE80211_SKB_CB(presp)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 928 | IEEE80211_SKB_CB(presp)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
| 923 | ieee80211_tx_skb(sdata, presp); | 929 | ieee80211_tx_skb(sdata, presp); |
| 924 | out: | 930 | out: |
| @@ -1039,7 +1045,7 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) | |||
| 1039 | mesh_mpp_table_grow(); | 1045 | mesh_mpp_table_grow(); |
| 1040 | 1046 | ||
| 1041 | if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) | 1047 | if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) |
| 1042 | ieee80211_mesh_housekeeping(sdata, ifmsh); | 1048 | ieee80211_mesh_housekeeping(sdata); |
| 1043 | 1049 | ||
| 1044 | if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags)) | 1050 | if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags)) |
| 1045 | ieee80211_mesh_rootpath(sdata); | 1051 | ieee80211_mesh_rootpath(sdata); |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 1a1da877b1d2..336c88a16687 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
| @@ -26,12 +26,12 @@ | |||
| 26 | * @MESH_PATH_ACTIVE: the mesh path can be used for forwarding | 26 | * @MESH_PATH_ACTIVE: the mesh path can be used for forwarding |
| 27 | * @MESH_PATH_RESOLVING: the discovery process is running for this mesh path | 27 | * @MESH_PATH_RESOLVING: the discovery process is running for this mesh path |
| 28 | * @MESH_PATH_SN_VALID: the mesh path contains a valid destination sequence | 28 | * @MESH_PATH_SN_VALID: the mesh path contains a valid destination sequence |
| 29 | * number | 29 | * number |
| 30 | * @MESH_PATH_FIXED: the mesh path has been manually set and should not be | 30 | * @MESH_PATH_FIXED: the mesh path has been manually set and should not be |
| 31 | * modified | 31 | * modified |
| 32 | * @MESH_PATH_RESOLVED: the mesh path can has been resolved | 32 | * @MESH_PATH_RESOLVED: the mesh path can has been resolved |
| 33 | * @MESH_PATH_REQ_QUEUED: there is an unsent path request for this destination | 33 | * @MESH_PATH_REQ_QUEUED: there is an unsent path request for this destination |
| 34 | * already queued up, waiting for the discovery process to start. | 34 | * already queued up, waiting for the discovery process to start. |
| 35 | * | 35 | * |
| 36 | * MESH_PATH_RESOLVED is used by the mesh path timer to | 36 | * MESH_PATH_RESOLVED is used by the mesh path timer to |
| 37 | * decide when to stop or cancel the mesh path discovery. | 37 | * decide when to stop or cancel the mesh path discovery. |
| @@ -73,16 +73,16 @@ enum mesh_deferred_task_flags { | |||
| 73 | * @dst: mesh path destination mac address | 73 | * @dst: mesh path destination mac address |
| 74 | * @sdata: mesh subif | 74 | * @sdata: mesh subif |
| 75 | * @next_hop: mesh neighbor to which frames for this destination will be | 75 | * @next_hop: mesh neighbor to which frames for this destination will be |
| 76 | * forwarded | 76 | * forwarded |
| 77 | * @timer: mesh path discovery timer | 77 | * @timer: mesh path discovery timer |
| 78 | * @frame_queue: pending queue for frames sent to this destination while the | 78 | * @frame_queue: pending queue for frames sent to this destination while the |
| 79 | * path is unresolved | 79 | * path is unresolved |
| 80 | * @sn: target sequence number | 80 | * @sn: target sequence number |
| 81 | * @metric: current metric to this destination | 81 | * @metric: current metric to this destination |
| 82 | * @hop_count: hops to destination | 82 | * @hop_count: hops to destination |
| 83 | * @exp_time: in jiffies, when the path will expire or when it expired | 83 | * @exp_time: in jiffies, when the path will expire or when it expired |
| 84 | * @discovery_timeout: timeout (lapse in jiffies) used for the last discovery | 84 | * @discovery_timeout: timeout (lapse in jiffies) used for the last discovery |
| 85 | * retry | 85 | * retry |
| 86 | * @discovery_retries: number of discovery retries | 86 | * @discovery_retries: number of discovery retries |
| 87 | * @flags: mesh path flags, as specified on &enum mesh_path_flags | 87 | * @flags: mesh path flags, as specified on &enum mesh_path_flags |
| 88 | * @state_lock: mesh path state lock used to protect changes to the | 88 | * @state_lock: mesh path state lock used to protect changes to the |
| @@ -206,38 +206,33 @@ struct mesh_rmc { | |||
| 206 | /* Various */ | 206 | /* Various */ |
| 207 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | 207 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, |
| 208 | const u8 *da, const u8 *sa); | 208 | const u8 *da, const u8 *sa); |
| 209 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | 209 | int ieee80211_new_mesh_header(struct ieee80211_sub_if_data *sdata, |
| 210 | struct ieee80211_sub_if_data *sdata, char *addr4or5, | 210 | struct ieee80211s_hdr *meshhdr, |
| 211 | char *addr6); | 211 | const char *addr4or5, const char *addr6); |
| 212 | int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, | 212 | int mesh_rmc_check(struct ieee80211_sub_if_data *sdata, |
| 213 | struct ieee80211_sub_if_data *sdata); | 213 | const u8 *addr, struct ieee80211s_hdr *mesh_hdr); |
| 214 | bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | 214 | bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, |
| 215 | struct ieee802_11_elems *ie); | 215 | struct ieee802_11_elems *ie); |
| 216 | void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); | 216 | void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); |
| 217 | void mesh_mgmt_ies_add(struct sk_buff *skb, | 217 | void mesh_mgmt_ies_add(struct ieee80211_sub_if_data *sdata, |
| 218 | struct ieee80211_sub_if_data *sdata); | 218 | struct sk_buff *skb); |
| 219 | int mesh_add_meshconf_ie(struct sk_buff *skb, | 219 | int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, |
| 220 | struct ieee80211_sub_if_data *sdata); | 220 | struct sk_buff *skb); |
| 221 | int mesh_add_meshid_ie(struct sk_buff *skb, | 221 | int mesh_add_meshid_ie(struct ieee80211_sub_if_data *sdata, |
| 222 | struct ieee80211_sub_if_data *sdata); | 222 | struct sk_buff *skb); |
| 223 | int mesh_add_rsn_ie(struct sk_buff *skb, | 223 | int mesh_add_rsn_ie(struct ieee80211_sub_if_data *sdata, |
| 224 | struct ieee80211_sub_if_data *sdata); | 224 | struct sk_buff *skb); |
| 225 | int mesh_add_awake_window_ie(struct sk_buff *skb, | 225 | int mesh_add_vendor_ies(struct ieee80211_sub_if_data *sdata, |
| 226 | struct ieee80211_sub_if_data *sdata); | 226 | struct sk_buff *skb); |
| 227 | int mesh_add_vendor_ies(struct sk_buff *skb, | 227 | int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata, |
| 228 | struct ieee80211_sub_if_data *sdata); | 228 | struct sk_buff *skb); |
| 229 | int mesh_add_ds_params_ie(struct sk_buff *skb, | 229 | int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata, |
| 230 | struct ieee80211_sub_if_data *sdata); | 230 | struct sk_buff *skb); |
| 231 | int mesh_add_ht_cap_ie(struct sk_buff *skb, | ||
| 232 | struct ieee80211_sub_if_data *sdata); | ||
| 233 | int mesh_add_ht_oper_ie(struct sk_buff *skb, | ||
| 234 | struct ieee80211_sub_if_data *sdata); | ||
| 235 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); | 231 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); |
| 236 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); | 232 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); |
| 237 | void ieee80211s_init(void); | 233 | void ieee80211s_init(void); |
| 238 | void ieee80211s_update_metric(struct ieee80211_local *local, | 234 | void ieee80211s_update_metric(struct ieee80211_local *local, |
| 239 | struct sta_info *sta, struct sk_buff *skb); | 235 | struct sta_info *sta, struct sk_buff *skb); |
| 240 | void ieee80211s_stop(void); | ||
| 241 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); | 236 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); |
| 242 | int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); | 237 | int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); |
| 243 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); | 238 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); |
| @@ -263,31 +258,32 @@ void ieee80211_mps_frame_release(struct sta_info *sta, | |||
| 263 | struct ieee802_11_elems *elems); | 258 | struct ieee802_11_elems *elems); |
| 264 | 259 | ||
| 265 | /* Mesh paths */ | 260 | /* Mesh paths */ |
| 266 | int mesh_nexthop_lookup(struct sk_buff *skb, | 261 | int mesh_nexthop_lookup(struct ieee80211_sub_if_data *sdata, |
| 267 | struct ieee80211_sub_if_data *sdata); | 262 | struct sk_buff *skb); |
| 268 | int mesh_nexthop_resolve(struct sk_buff *skb, | 263 | int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata, |
| 269 | struct ieee80211_sub_if_data *sdata); | 264 | struct sk_buff *skb); |
| 270 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); | 265 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); |
| 271 | struct mesh_path *mesh_path_lookup(const u8 *dst, | 266 | struct mesh_path *mesh_path_lookup(struct ieee80211_sub_if_data *sdata, |
| 272 | struct ieee80211_sub_if_data *sdata); | 267 | const u8 *dst); |
| 273 | struct mesh_path *mpp_path_lookup(u8 *dst, | 268 | struct mesh_path *mpp_path_lookup(struct ieee80211_sub_if_data *sdata, |
| 274 | struct ieee80211_sub_if_data *sdata); | 269 | const u8 *dst); |
| 275 | int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata); | 270 | int mpp_path_add(struct ieee80211_sub_if_data *sdata, |
| 276 | struct mesh_path *mesh_path_lookup_by_idx(int idx, | 271 | const u8 *dst, const u8 *mpp); |
| 277 | struct ieee80211_sub_if_data *sdata); | 272 | struct mesh_path * |
| 273 | mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx); | ||
| 278 | void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); | 274 | void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); |
| 279 | void mesh_path_expire(struct ieee80211_sub_if_data *sdata); | 275 | void mesh_path_expire(struct ieee80211_sub_if_data *sdata); |
| 280 | void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, | 276 | void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, |
| 281 | struct ieee80211_mgmt *mgmt, size_t len); | 277 | struct ieee80211_mgmt *mgmt, size_t len); |
| 282 | int mesh_path_add(const u8 *dst, struct ieee80211_sub_if_data *sdata); | 278 | int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst); |
| 283 | 279 | ||
| 284 | int mesh_path_add_gate(struct mesh_path *mpath); | 280 | int mesh_path_add_gate(struct mesh_path *mpath); |
| 285 | int mesh_path_send_to_gates(struct mesh_path *mpath); | 281 | int mesh_path_send_to_gates(struct mesh_path *mpath); |
| 286 | int mesh_gate_num(struct ieee80211_sub_if_data *sdata); | 282 | int mesh_gate_num(struct ieee80211_sub_if_data *sdata); |
| 283 | |||
| 287 | /* Mesh plinks */ | 284 | /* Mesh plinks */ |
| 288 | void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, | 285 | void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, |
| 289 | u8 *hw_addr, | 286 | u8 *hw_addr, struct ieee802_11_elems *ie); |
| 290 | struct ieee802_11_elems *ie); | ||
| 291 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); | 287 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); |
| 292 | u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); | 288 | u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); |
| 293 | void mesh_plink_broken(struct sta_info *sta); | 289 | void mesh_plink_broken(struct sta_info *sta); |
| @@ -304,19 +300,19 @@ void mesh_sta_cleanup(struct sta_info *sta); | |||
| 304 | void mesh_mpath_table_grow(void); | 300 | void mesh_mpath_table_grow(void); |
| 305 | void mesh_mpp_table_grow(void); | 301 | void mesh_mpp_table_grow(void); |
| 306 | /* Mesh paths */ | 302 | /* Mesh paths */ |
| 307 | int mesh_path_error_tx(u8 ttl, const u8 *target, __le32 target_sn, | 303 | int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, |
| 308 | __le16 target_rcode, const u8 *ra, | 304 | u8 ttl, const u8 *target, __le32 target_sn, |
| 309 | struct ieee80211_sub_if_data *sdata); | 305 | __le16 target_rcode, const u8 *ra); |
| 310 | void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); | 306 | void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); |
| 311 | void mesh_path_flush_pending(struct mesh_path *mpath); | 307 | void mesh_path_flush_pending(struct mesh_path *mpath); |
| 312 | void mesh_path_tx_pending(struct mesh_path *mpath); | 308 | void mesh_path_tx_pending(struct mesh_path *mpath); |
| 313 | int mesh_pathtbl_init(void); | 309 | int mesh_pathtbl_init(void); |
| 314 | void mesh_pathtbl_unregister(void); | 310 | void mesh_pathtbl_unregister(void); |
| 315 | int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata); | 311 | int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr); |
| 316 | void mesh_path_timer(unsigned long data); | 312 | void mesh_path_timer(unsigned long data); |
| 317 | void mesh_path_flush_by_nexthop(struct sta_info *sta); | 313 | void mesh_path_flush_by_nexthop(struct sta_info *sta); |
| 318 | void mesh_path_discard_frame(struct sk_buff *skb, | 314 | void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata, |
| 319 | struct ieee80211_sub_if_data *sdata); | 315 | struct sk_buff *skb); |
| 320 | void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); | 316 | void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); |
| 321 | void mesh_path_restart(struct ieee80211_sub_if_data *sdata); | 317 | void mesh_path_restart(struct ieee80211_sub_if_data *sdata); |
| 322 | void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); | 318 | 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); | |||
| 325 | extern int mesh_paths_generation; | 321 | extern int mesh_paths_generation; |
| 326 | 322 | ||
| 327 | #ifdef CONFIG_MAC80211_MESH | 323 | #ifdef CONFIG_MAC80211_MESH |
| 328 | extern int mesh_allocated; | ||
| 329 | |||
| 330 | static inline | 324 | static inline |
| 331 | u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) | 325 | u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) |
| 332 | { | 326 | { |
| @@ -371,8 +365,8 @@ void mesh_plink_quiesce(struct sta_info *sta); | |||
| 371 | void mesh_plink_restart(struct sta_info *sta); | 365 | void mesh_plink_restart(struct sta_info *sta); |
| 372 | void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); | 366 | void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); |
| 373 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); | 367 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); |
| 368 | void ieee80211s_stop(void); | ||
| 374 | #else | 369 | #else |
| 375 | #define mesh_allocated 0 | ||
| 376 | static inline void | 370 | static inline void |
| 377 | ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} | 371 | ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} |
| 378 | static inline void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) | 372 | 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) | |||
| 385 | { return false; } | 379 | { return false; } |
| 386 | static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) | 380 | static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) |
| 387 | {} | 381 | {} |
| 382 | static inline void ieee80211s_stop(void) {} | ||
| 388 | #endif | 383 | #endif |
| 389 | 384 | ||
| 390 | #endif /* IEEE80211S_H */ | 385 | #endif /* IEEE80211S_H */ |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 585c1e26cca8..bdb8d3b14587 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
| @@ -238,9 +238,9 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata, | |||
| 238 | * also acquires in the TX path. To avoid a deadlock we don't transmit the | 238 | * also acquires in the TX path. To avoid a deadlock we don't transmit the |
| 239 | * frame directly but add it to the pending queue instead. | 239 | * frame directly but add it to the pending queue instead. |
| 240 | */ | 240 | */ |
| 241 | int mesh_path_error_tx(u8 ttl, const u8 *target, __le32 target_sn, | 241 | int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, |
| 242 | __le16 target_rcode, const u8 *ra, | 242 | u8 ttl, const u8 *target, __le32 target_sn, |
| 243 | struct ieee80211_sub_if_data *sdata) | 243 | __le16 target_rcode, const u8 *ra) |
| 244 | { | 244 | { |
| 245 | struct ieee80211_local *local = sdata->local; | 245 | struct ieee80211_local *local = sdata->local; |
| 246 | struct sk_buff *skb; | 246 | struct sk_buff *skb; |
| @@ -430,7 +430,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
| 430 | process = false; | 430 | process = false; |
| 431 | fresh_info = false; | 431 | fresh_info = false; |
| 432 | } else { | 432 | } else { |
| 433 | mpath = mesh_path_lookup(orig_addr, sdata); | 433 | mpath = mesh_path_lookup(sdata, orig_addr); |
| 434 | if (mpath) { | 434 | if (mpath) { |
| 435 | spin_lock_bh(&mpath->state_lock); | 435 | spin_lock_bh(&mpath->state_lock); |
| 436 | if (mpath->flags & MESH_PATH_FIXED) | 436 | if (mpath->flags & MESH_PATH_FIXED) |
| @@ -445,8 +445,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
| 445 | } | 445 | } |
| 446 | } | 446 | } |
| 447 | } else { | 447 | } else { |
| 448 | mesh_path_add(orig_addr, sdata); | 448 | mesh_path_add(sdata, orig_addr); |
| 449 | mpath = mesh_path_lookup(orig_addr, sdata); | 449 | mpath = mesh_path_lookup(sdata, orig_addr); |
| 450 | if (!mpath) { | 450 | if (!mpath) { |
| 451 | rcu_read_unlock(); | 451 | rcu_read_unlock(); |
| 452 | return 0; | 452 | return 0; |
| @@ -478,7 +478,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
| 478 | else { | 478 | else { |
| 479 | fresh_info = true; | 479 | fresh_info = true; |
| 480 | 480 | ||
| 481 | mpath = mesh_path_lookup(ta, sdata); | 481 | mpath = mesh_path_lookup(sdata, ta); |
| 482 | if (mpath) { | 482 | if (mpath) { |
| 483 | spin_lock_bh(&mpath->state_lock); | 483 | spin_lock_bh(&mpath->state_lock); |
| 484 | if ((mpath->flags & MESH_PATH_FIXED) || | 484 | if ((mpath->flags & MESH_PATH_FIXED) || |
| @@ -486,8 +486,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
| 486 | (last_hop_metric > mpath->metric))) | 486 | (last_hop_metric > mpath->metric))) |
| 487 | fresh_info = false; | 487 | fresh_info = false; |
| 488 | } else { | 488 | } else { |
| 489 | mesh_path_add(ta, sdata); | 489 | mesh_path_add(sdata, ta); |
| 490 | mpath = mesh_path_lookup(ta, sdata); | 490 | mpath = mesh_path_lookup(sdata, ta); |
| 491 | if (!mpath) { | 491 | if (!mpath) { |
| 492 | rcu_read_unlock(); | 492 | rcu_read_unlock(); |
| 493 | return 0; | 493 | return 0; |
| @@ -553,7 +553,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
| 553 | } else if (is_broadcast_ether_addr(target_addr) && | 553 | } else if (is_broadcast_ether_addr(target_addr) && |
| 554 | (target_flags & IEEE80211_PREQ_TO_FLAG)) { | 554 | (target_flags & IEEE80211_PREQ_TO_FLAG)) { |
| 555 | rcu_read_lock(); | 555 | rcu_read_lock(); |
| 556 | mpath = mesh_path_lookup(orig_addr, sdata); | 556 | mpath = mesh_path_lookup(sdata, orig_addr); |
| 557 | if (mpath) { | 557 | if (mpath) { |
| 558 | if (flags & IEEE80211_PREQ_PROACTIVE_PREP_FLAG) { | 558 | if (flags & IEEE80211_PREQ_PROACTIVE_PREP_FLAG) { |
| 559 | reply = true; | 559 | reply = true; |
| @@ -568,7 +568,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
| 568 | rcu_read_unlock(); | 568 | rcu_read_unlock(); |
| 569 | } else { | 569 | } else { |
| 570 | rcu_read_lock(); | 570 | rcu_read_lock(); |
| 571 | mpath = mesh_path_lookup(target_addr, sdata); | 571 | mpath = mesh_path_lookup(sdata, target_addr); |
| 572 | if (mpath) { | 572 | if (mpath) { |
| 573 | if ((!(mpath->flags & MESH_PATH_SN_VALID)) || | 573 | if ((!(mpath->flags & MESH_PATH_SN_VALID)) || |
| 574 | SN_LT(mpath->sn, target_sn)) { | 574 | SN_LT(mpath->sn, target_sn)) { |
| @@ -678,7 +678,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
| 678 | } | 678 | } |
| 679 | 679 | ||
| 680 | rcu_read_lock(); | 680 | rcu_read_lock(); |
| 681 | mpath = mesh_path_lookup(orig_addr, sdata); | 681 | mpath = mesh_path_lookup(sdata, orig_addr); |
| 682 | if (mpath) | 682 | if (mpath) |
| 683 | spin_lock_bh(&mpath->state_lock); | 683 | spin_lock_bh(&mpath->state_lock); |
| 684 | else | 684 | else |
| @@ -736,7 +736,7 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, | |||
| 736 | target_rcode = PERR_IE_TARGET_RCODE(perr_elem); | 736 | target_rcode = PERR_IE_TARGET_RCODE(perr_elem); |
| 737 | 737 | ||
| 738 | rcu_read_lock(); | 738 | rcu_read_lock(); |
| 739 | mpath = mesh_path_lookup(target_addr, sdata); | 739 | mpath = mesh_path_lookup(sdata, target_addr); |
| 740 | if (mpath) { | 740 | if (mpath) { |
| 741 | struct sta_info *sta; | 741 | struct sta_info *sta; |
| 742 | 742 | ||
| @@ -751,9 +751,10 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, | |||
| 751 | spin_unlock_bh(&mpath->state_lock); | 751 | spin_unlock_bh(&mpath->state_lock); |
| 752 | if (!ifmsh->mshcfg.dot11MeshForwarding) | 752 | if (!ifmsh->mshcfg.dot11MeshForwarding) |
| 753 | goto endperr; | 753 | goto endperr; |
| 754 | mesh_path_error_tx(ttl, target_addr, cpu_to_le32(target_sn), | 754 | mesh_path_error_tx(sdata, ttl, target_addr, |
| 755 | cpu_to_le32(target_sn), | ||
| 755 | cpu_to_le16(target_rcode), | 756 | cpu_to_le16(target_rcode), |
| 756 | broadcast_addr, sdata); | 757 | broadcast_addr); |
| 757 | } else | 758 | } else |
| 758 | spin_unlock_bh(&mpath->state_lock); | 759 | spin_unlock_bh(&mpath->state_lock); |
| 759 | } | 760 | } |
| @@ -801,10 +802,10 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
| 801 | 802 | ||
| 802 | metric_txsta = airtime_link_metric_get(local, sta); | 803 | metric_txsta = airtime_link_metric_get(local, sta); |
| 803 | 804 | ||
| 804 | mpath = mesh_path_lookup(orig_addr, sdata); | 805 | mpath = mesh_path_lookup(sdata, orig_addr); |
| 805 | if (!mpath) { | 806 | if (!mpath) { |
| 806 | mesh_path_add(orig_addr, sdata); | 807 | mesh_path_add(sdata, orig_addr); |
| 807 | mpath = mesh_path_lookup(orig_addr, sdata); | 808 | mpath = mesh_path_lookup(sdata, orig_addr); |
| 808 | if (!mpath) { | 809 | if (!mpath) { |
| 809 | rcu_read_unlock(); | 810 | rcu_read_unlock(); |
| 810 | sdata->u.mesh.mshstats.dropped_frames_no_route++; | 811 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
| @@ -861,8 +862,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
| 861 | 862 | ||
| 862 | 863 | ||
| 863 | void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, | 864 | void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, |
| 864 | struct ieee80211_mgmt *mgmt, | 865 | struct ieee80211_mgmt *mgmt, size_t len) |
| 865 | size_t len) | ||
| 866 | { | 866 | { |
| 867 | struct ieee802_11_elems elems; | 867 | struct ieee802_11_elems elems; |
| 868 | size_t baselen; | 868 | size_t baselen; |
| @@ -1006,7 +1006,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | |||
| 1006 | spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); | 1006 | spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); |
| 1007 | 1007 | ||
| 1008 | rcu_read_lock(); | 1008 | rcu_read_lock(); |
| 1009 | mpath = mesh_path_lookup(preq_node->dst, sdata); | 1009 | mpath = mesh_path_lookup(sdata, preq_node->dst); |
| 1010 | if (!mpath) | 1010 | if (!mpath) |
| 1011 | goto enddiscovery; | 1011 | goto enddiscovery; |
| 1012 | 1012 | ||
| @@ -1076,8 +1076,8 @@ enddiscovery: | |||
| 1076 | * Returns: 0 if the next hop was found and -ENOENT if the frame was queued. | 1076 | * Returns: 0 if the next hop was found and -ENOENT if the frame was queued. |
| 1077 | * skb is freeed here if no mpath could be allocated. | 1077 | * skb is freeed here if no mpath could be allocated. |
| 1078 | */ | 1078 | */ |
| 1079 | int mesh_nexthop_resolve(struct sk_buff *skb, | 1079 | int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata, |
| 1080 | struct ieee80211_sub_if_data *sdata) | 1080 | struct sk_buff *skb) |
| 1081 | { | 1081 | { |
| 1082 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1082 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
| 1083 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1083 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| @@ -1091,17 +1091,17 @@ int mesh_nexthop_resolve(struct sk_buff *skb, | |||
| 1091 | return 0; | 1091 | return 0; |
| 1092 | 1092 | ||
| 1093 | rcu_read_lock(); | 1093 | rcu_read_lock(); |
| 1094 | err = mesh_nexthop_lookup(skb, sdata); | 1094 | err = mesh_nexthop_lookup(sdata, skb); |
| 1095 | if (!err) | 1095 | if (!err) |
| 1096 | goto endlookup; | 1096 | goto endlookup; |
| 1097 | 1097 | ||
| 1098 | /* no nexthop found, start resolving */ | 1098 | /* no nexthop found, start resolving */ |
| 1099 | mpath = mesh_path_lookup(target_addr, sdata); | 1099 | mpath = mesh_path_lookup(sdata, target_addr); |
| 1100 | if (!mpath) { | 1100 | if (!mpath) { |
| 1101 | mesh_path_add(target_addr, sdata); | 1101 | mesh_path_add(sdata, target_addr); |
| 1102 | mpath = mesh_path_lookup(target_addr, sdata); | 1102 | mpath = mesh_path_lookup(sdata, target_addr); |
| 1103 | if (!mpath) { | 1103 | if (!mpath) { |
| 1104 | mesh_path_discard_frame(skb, sdata); | 1104 | mesh_path_discard_frame(sdata, skb); |
| 1105 | err = -ENOSPC; | 1105 | err = -ENOSPC; |
| 1106 | goto endlookup; | 1106 | goto endlookup; |
| 1107 | } | 1107 | } |
| @@ -1118,12 +1118,13 @@ int mesh_nexthop_resolve(struct sk_buff *skb, | |||
| 1118 | skb_queue_tail(&mpath->frame_queue, skb); | 1118 | skb_queue_tail(&mpath->frame_queue, skb); |
| 1119 | err = -ENOENT; | 1119 | err = -ENOENT; |
| 1120 | if (skb_to_free) | 1120 | if (skb_to_free) |
| 1121 | mesh_path_discard_frame(skb_to_free, sdata); | 1121 | mesh_path_discard_frame(sdata, skb_to_free); |
| 1122 | 1122 | ||
| 1123 | endlookup: | 1123 | endlookup: |
| 1124 | rcu_read_unlock(); | 1124 | rcu_read_unlock(); |
| 1125 | return err; | 1125 | return err; |
| 1126 | } | 1126 | } |
| 1127 | |||
| 1127 | /** | 1128 | /** |
| 1128 | * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling | 1129 | * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling |
| 1129 | * this function is considered "using" the associated mpath, so preempt a path | 1130 | * this function is considered "using" the associated mpath, so preempt a path |
| @@ -1134,8 +1135,8 @@ endlookup: | |||
| 1134 | * | 1135 | * |
| 1135 | * Returns: 0 if the next hop was found. Nonzero otherwise. | 1136 | * Returns: 0 if the next hop was found. Nonzero otherwise. |
| 1136 | */ | 1137 | */ |
| 1137 | int mesh_nexthop_lookup(struct sk_buff *skb, | 1138 | int mesh_nexthop_lookup(struct ieee80211_sub_if_data *sdata, |
| 1138 | struct ieee80211_sub_if_data *sdata) | 1139 | struct sk_buff *skb) |
| 1139 | { | 1140 | { |
| 1140 | struct mesh_path *mpath; | 1141 | struct mesh_path *mpath; |
| 1141 | struct sta_info *next_hop; | 1142 | struct sta_info *next_hop; |
| @@ -1144,7 +1145,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
| 1144 | int err = -ENOENT; | 1145 | int err = -ENOENT; |
| 1145 | 1146 | ||
| 1146 | rcu_read_lock(); | 1147 | rcu_read_lock(); |
| 1147 | mpath = mesh_path_lookup(target_addr, sdata); | 1148 | mpath = mesh_path_lookup(sdata, target_addr); |
| 1148 | 1149 | ||
| 1149 | if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE)) | 1150 | if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE)) |
| 1150 | goto endlookup; | 1151 | goto endlookup; |
| @@ -1203,8 +1204,7 @@ void mesh_path_timer(unsigned long data) | |||
| 1203 | } | 1204 | } |
| 1204 | } | 1205 | } |
| 1205 | 1206 | ||
| 1206 | void | 1207 | void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) |
| 1207 | mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) | ||
| 1208 | { | 1208 | { |
| 1209 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 1209 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
| 1210 | u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval; | 1210 | u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval; |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 2ce4c4023a97..6b3c4e119c63 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
| @@ -24,9 +24,12 @@ | |||
| 24 | /* Keep the mean chain length below this constant */ | 24 | /* Keep the mean chain length below this constant */ |
| 25 | #define MEAN_CHAIN_LEN 2 | 25 | #define MEAN_CHAIN_LEN 2 |
| 26 | 26 | ||
| 27 | #define MPATH_EXPIRED(mpath) ((mpath->flags & MESH_PATH_ACTIVE) && \ | 27 | static inline bool mpath_expired(struct mesh_path *mpath) |
| 28 | time_after(jiffies, mpath->exp_time) && \ | 28 | { |
| 29 | !(mpath->flags & MESH_PATH_FIXED)) | 29 | return (mpath->flags & MESH_PATH_ACTIVE) && |
| 30 | time_after(jiffies, mpath->exp_time) && | ||
| 31 | !(mpath->flags & MESH_PATH_FIXED); | ||
| 32 | } | ||
| 30 | 33 | ||
| 31 | struct mpath_node { | 34 | struct mpath_node { |
| 32 | struct hlist_node list; | 35 | struct hlist_node list; |
| @@ -185,8 +188,8 @@ static u32 mesh_table_hash(const u8 *addr, struct ieee80211_sub_if_data *sdata, | |||
| 185 | struct mesh_table *tbl) | 188 | struct mesh_table *tbl) |
| 186 | { | 189 | { |
| 187 | /* Use last four bytes of hw addr and interface index as hash index */ | 190 | /* Use last four bytes of hw addr and interface index as hash index */ |
| 188 | return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, tbl->hash_rnd) | 191 | return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, |
| 189 | & tbl->hash_mask; | 192 | tbl->hash_rnd) & tbl->hash_mask; |
| 190 | } | 193 | } |
| 191 | 194 | ||
| 192 | 195 | ||
| @@ -339,7 +342,7 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst, | |||
| 339 | mpath = node->mpath; | 342 | mpath = node->mpath; |
| 340 | if (mpath->sdata == sdata && | 343 | if (mpath->sdata == sdata && |
| 341 | ether_addr_equal(dst, mpath->dst)) { | 344 | ether_addr_equal(dst, mpath->dst)) { |
| 342 | if (MPATH_EXPIRED(mpath)) { | 345 | if (mpath_expired(mpath)) { |
| 343 | spin_lock_bh(&mpath->state_lock); | 346 | spin_lock_bh(&mpath->state_lock); |
| 344 | mpath->flags &= ~MESH_PATH_ACTIVE; | 347 | mpath->flags &= ~MESH_PATH_ACTIVE; |
| 345 | spin_unlock_bh(&mpath->state_lock); | 348 | spin_unlock_bh(&mpath->state_lock); |
| @@ -352,20 +355,21 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst, | |||
| 352 | 355 | ||
| 353 | /** | 356 | /** |
| 354 | * mesh_path_lookup - look up a path in the mesh path table | 357 | * mesh_path_lookup - look up a path in the mesh path table |
| 355 | * @dst: hardware address (ETH_ALEN length) of destination | ||
| 356 | * @sdata: local subif | 358 | * @sdata: local subif |
| 359 | * @dst: hardware address (ETH_ALEN length) of destination | ||
| 357 | * | 360 | * |
| 358 | * Returns: pointer to the mesh path structure, or NULL if not found | 361 | * Returns: pointer to the mesh path structure, or NULL if not found |
| 359 | * | 362 | * |
| 360 | * Locking: must be called within a read rcu section. | 363 | * Locking: must be called within a read rcu section. |
| 361 | */ | 364 | */ |
| 362 | struct mesh_path *mesh_path_lookup(const u8 *dst, | 365 | struct mesh_path * |
| 363 | struct ieee80211_sub_if_data *sdata) | 366 | mesh_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) |
| 364 | { | 367 | { |
| 365 | return mpath_lookup(rcu_dereference(mesh_paths), dst, sdata); | 368 | return mpath_lookup(rcu_dereference(mesh_paths), dst, sdata); |
| 366 | } | 369 | } |
| 367 | 370 | ||
| 368 | struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | 371 | struct mesh_path * |
| 372 | mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) | ||
| 369 | { | 373 | { |
| 370 | return mpath_lookup(rcu_dereference(mpp_paths), dst, sdata); | 374 | return mpath_lookup(rcu_dereference(mpp_paths), dst, sdata); |
| 371 | } | 375 | } |
| @@ -380,7 +384,8 @@ struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
| 380 | * | 384 | * |
| 381 | * Locking: must be called within a read rcu section. | 385 | * Locking: must be called within a read rcu section. |
| 382 | */ | 386 | */ |
| 383 | struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data *sdata) | 387 | struct mesh_path * |
| 388 | mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) | ||
| 384 | { | 389 | { |
| 385 | struct mesh_table *tbl = rcu_dereference(mesh_paths); | 390 | struct mesh_table *tbl = rcu_dereference(mesh_paths); |
| 386 | struct mpath_node *node; | 391 | struct mpath_node *node; |
| @@ -392,7 +397,7 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data | |||
| 392 | if (sdata && node->mpath->sdata != sdata) | 397 | if (sdata && node->mpath->sdata != sdata) |
| 393 | continue; | 398 | continue; |
| 394 | if (j++ == idx) { | 399 | if (j++ == idx) { |
| 395 | if (MPATH_EXPIRED(node->mpath)) { | 400 | if (mpath_expired(node->mpath)) { |
| 396 | spin_lock_bh(&node->mpath->state_lock); | 401 | spin_lock_bh(&node->mpath->state_lock); |
| 397 | node->mpath->flags &= ~MESH_PATH_ACTIVE; | 402 | node->mpath->flags &= ~MESH_PATH_ACTIVE; |
| 398 | spin_unlock_bh(&node->mpath->state_lock); | 403 | spin_unlock_bh(&node->mpath->state_lock); |
| @@ -436,11 +441,10 @@ int mesh_path_add_gate(struct mesh_path *mpath) | |||
| 436 | spin_lock_bh(&tbl->gates_lock); | 441 | spin_lock_bh(&tbl->gates_lock); |
| 437 | hlist_add_head_rcu(&new_gate->list, tbl->known_gates); | 442 | hlist_add_head_rcu(&new_gate->list, tbl->known_gates); |
| 438 | spin_unlock_bh(&tbl->gates_lock); | 443 | spin_unlock_bh(&tbl->gates_lock); |
| 439 | rcu_read_unlock(); | ||
| 440 | mpath_dbg(mpath->sdata, | 444 | mpath_dbg(mpath->sdata, |
| 441 | "Mesh path: Recorded new gate: %pM. %d known gates\n", | 445 | "Mesh path: Recorded new gate: %pM. %d known gates\n", |
| 442 | mpath->dst, mpath->sdata->u.mesh.num_gates); | 446 | mpath->dst, mpath->sdata->u.mesh.num_gates); |
| 443 | return 0; | 447 | err = 0; |
| 444 | err_rcu: | 448 | err_rcu: |
| 445 | rcu_read_unlock(); | 449 | rcu_read_unlock(); |
| 446 | return err; | 450 | return err; |
| @@ -451,30 +455,27 @@ err_rcu: | |||
| 451 | * @tbl: table which holds our list of known gates | 455 | * @tbl: table which holds our list of known gates |
| 452 | * @mpath: gate mpath | 456 | * @mpath: gate mpath |
| 453 | * | 457 | * |
| 454 | * Returns: 0 on success | ||
| 455 | * | ||
| 456 | * Locking: must be called inside rcu_read_lock() section | 458 | * Locking: must be called inside rcu_read_lock() section |
| 457 | */ | 459 | */ |
| 458 | static int mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath) | 460 | static void mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath) |
| 459 | { | 461 | { |
| 460 | struct mpath_node *gate; | 462 | struct mpath_node *gate; |
| 461 | struct hlist_node *p, *q; | 463 | struct hlist_node *p, *q; |
| 462 | 464 | ||
| 463 | hlist_for_each_entry_safe(gate, p, q, tbl->known_gates, list) | 465 | hlist_for_each_entry_safe(gate, p, q, tbl->known_gates, list) { |
| 464 | if (gate->mpath == mpath) { | 466 | if (gate->mpath != mpath) |
| 465 | spin_lock_bh(&tbl->gates_lock); | 467 | continue; |
| 466 | hlist_del_rcu(&gate->list); | 468 | spin_lock_bh(&tbl->gates_lock); |
| 467 | kfree_rcu(gate, rcu); | 469 | hlist_del_rcu(&gate->list); |
| 468 | spin_unlock_bh(&tbl->gates_lock); | 470 | kfree_rcu(gate, rcu); |
| 469 | mpath->sdata->u.mesh.num_gates--; | 471 | spin_unlock_bh(&tbl->gates_lock); |
| 470 | mpath->is_gate = false; | 472 | mpath->sdata->u.mesh.num_gates--; |
| 471 | mpath_dbg(mpath->sdata, | 473 | mpath->is_gate = false; |
| 472 | "Mesh path: Deleted gate: %pM. %d known gates\n", | 474 | mpath_dbg(mpath->sdata, |
| 473 | mpath->dst, mpath->sdata->u.mesh.num_gates); | 475 | "Mesh path: Deleted gate: %pM. %d known gates\n", |
| 474 | break; | 476 | mpath->dst, mpath->sdata->u.mesh.num_gates); |
| 475 | } | 477 | break; |
| 476 | 478 | } | |
| 477 | return 0; | ||
| 478 | } | 479 | } |
| 479 | 480 | ||
| 480 | /** | 481 | /** |
| @@ -488,14 +489,14 @@ int mesh_gate_num(struct ieee80211_sub_if_data *sdata) | |||
| 488 | 489 | ||
| 489 | /** | 490 | /** |
| 490 | * mesh_path_add - allocate and add a new path to the mesh path table | 491 | * mesh_path_add - allocate and add a new path to the mesh path table |
| 491 | * @addr: destination address of the path (ETH_ALEN length) | 492 | * @dst: destination address of the path (ETH_ALEN length) |
| 492 | * @sdata: local subif | 493 | * @sdata: local subif |
| 493 | * | 494 | * |
| 494 | * Returns: 0 on success | 495 | * Returns: 0 on success |
| 495 | * | 496 | * |
| 496 | * State: the initial state of the new path is set to 0 | 497 | * State: the initial state of the new path is set to 0 |
| 497 | */ | 498 | */ |
| 498 | int mesh_path_add(const u8 *dst, struct ieee80211_sub_if_data *sdata) | 499 | int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst) |
| 499 | { | 500 | { |
| 500 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 501 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
| 501 | struct ieee80211_local *local = sdata->local; | 502 | struct ieee80211_local *local = sdata->local; |
| @@ -630,7 +631,8 @@ void mesh_mpp_table_grow(void) | |||
| 630 | write_unlock_bh(&pathtbl_resize_lock); | 631 | write_unlock_bh(&pathtbl_resize_lock); |
| 631 | } | 632 | } |
| 632 | 633 | ||
| 633 | int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | 634 | int mpp_path_add(struct ieee80211_sub_if_data *sdata, |
| 635 | const u8 *dst, const u8 *mpp) | ||
| 634 | { | 636 | { |
| 635 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 637 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
| 636 | struct ieee80211_local *local = sdata->local; | 638 | struct ieee80211_local *local = sdata->local; |
| @@ -739,9 +741,10 @@ void mesh_plink_broken(struct sta_info *sta) | |||
| 739 | mpath->flags &= ~MESH_PATH_ACTIVE; | 741 | mpath->flags &= ~MESH_PATH_ACTIVE; |
| 740 | ++mpath->sn; | 742 | ++mpath->sn; |
| 741 | spin_unlock_bh(&mpath->state_lock); | 743 | spin_unlock_bh(&mpath->state_lock); |
| 742 | mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, | 744 | mesh_path_error_tx(sdata, |
| 743 | mpath->dst, cpu_to_le32(mpath->sn), | 745 | sdata->u.mesh.mshcfg.element_ttl, |
| 744 | reason, bcast, sdata); | 746 | mpath->dst, cpu_to_le32(mpath->sn), |
| 747 | reason, bcast); | ||
| 745 | } | 748 | } |
| 746 | } | 749 | } |
| 747 | rcu_read_unlock(); | 750 | rcu_read_unlock(); |
| @@ -856,7 +859,7 @@ void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) | |||
| 856 | * | 859 | * |
| 857 | * Returns: 0 if successful | 860 | * Returns: 0 if successful |
| 858 | */ | 861 | */ |
| 859 | int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) | 862 | int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr) |
| 860 | { | 863 | { |
| 861 | struct mesh_table *tbl; | 864 | struct mesh_table *tbl; |
| 862 | struct mesh_path *mpath; | 865 | struct mesh_path *mpath; |
| @@ -965,8 +968,8 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) | |||
| 965 | * | 968 | * |
| 966 | * Locking: the function must me called within a rcu_read_lock region | 969 | * Locking: the function must me called within a rcu_read_lock region |
| 967 | */ | 970 | */ |
| 968 | void mesh_path_discard_frame(struct sk_buff *skb, | 971 | void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata, |
| 969 | struct ieee80211_sub_if_data *sdata) | 972 | struct sk_buff *skb) |
| 970 | { | 973 | { |
| 971 | kfree_skb(skb); | 974 | kfree_skb(skb); |
| 972 | sdata->u.mesh.mshstats.dropped_frames_no_route++; | 975 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
| @@ -984,7 +987,7 @@ void mesh_path_flush_pending(struct mesh_path *mpath) | |||
| 984 | struct sk_buff *skb; | 987 | struct sk_buff *skb; |
| 985 | 988 | ||
| 986 | while ((skb = skb_dequeue(&mpath->frame_queue)) != NULL) | 989 | while ((skb = skb_dequeue(&mpath->frame_queue)) != NULL) |
| 987 | mesh_path_discard_frame(skb, mpath->sdata); | 990 | mesh_path_discard_frame(mpath->sdata, skb); |
| 988 | } | 991 | } |
| 989 | 992 | ||
| 990 | /** | 993 | /** |
| @@ -1105,7 +1108,7 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata) | |||
| 1105 | if ((!(mpath->flags & MESH_PATH_RESOLVING)) && | 1108 | if ((!(mpath->flags & MESH_PATH_RESOLVING)) && |
| 1106 | (!(mpath->flags & MESH_PATH_FIXED)) && | 1109 | (!(mpath->flags & MESH_PATH_FIXED)) && |
| 1107 | time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) | 1110 | time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) |
| 1108 | mesh_path_del(mpath->dst, mpath->sdata); | 1111 | mesh_path_del(mpath->sdata, mpath->dst); |
| 1109 | } | 1112 | } |
| 1110 | rcu_read_unlock(); | 1113 | rcu_read_unlock(); |
| 1111 | } | 1114 | } |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index f7526e509aa8..07d396d57079 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
| @@ -37,9 +37,31 @@ enum plink_event { | |||
| 37 | CLS_IGNR | 37 | CLS_IGNR |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | static const char * const mplstates[] = { | ||
| 41 | [NL80211_PLINK_LISTEN] = "LISTEN", | ||
| 42 | [NL80211_PLINK_OPN_SNT] = "OPN-SNT", | ||
| 43 | [NL80211_PLINK_OPN_RCVD] = "OPN-RCVD", | ||
| 44 | [NL80211_PLINK_CNF_RCVD] = "CNF_RCVD", | ||
| 45 | [NL80211_PLINK_ESTAB] = "ESTAB", | ||
| 46 | [NL80211_PLINK_HOLDING] = "HOLDING", | ||
| 47 | [NL80211_PLINK_BLOCKED] = "BLOCKED" | ||
| 48 | }; | ||
| 49 | |||
| 50 | static const char * const mplevents[] = { | ||
| 51 | [PLINK_UNDEFINED] = "NONE", | ||
| 52 | [OPN_ACPT] = "OPN_ACPT", | ||
| 53 | [OPN_RJCT] = "OPN_RJCT", | ||
| 54 | [OPN_IGNR] = "OPN_IGNR", | ||
| 55 | [CNF_ACPT] = "CNF_ACPT", | ||
| 56 | [CNF_RJCT] = "CNF_RJCT", | ||
| 57 | [CNF_IGNR] = "CNF_IGNR", | ||
| 58 | [CLS_ACPT] = "CLS_ACPT", | ||
| 59 | [CLS_IGNR] = "CLS_IGNR" | ||
| 60 | }; | ||
| 61 | |||
| 40 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | 62 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, |
| 41 | enum ieee80211_self_protected_actioncode action, | 63 | enum ieee80211_self_protected_actioncode action, |
| 42 | u8 *da, __le16 llid, __le16 plid, __le16 reason); | 64 | u8 *da, __le16 llid, __le16 plid, __le16 reason); |
| 43 | 65 | ||
| 44 | /** | 66 | /** |
| 45 | * mesh_plink_fsm_restart - restart a mesh peer link finite state machine | 67 | * mesh_plink_fsm_restart - restart a mesh peer link finite state machine |
| @@ -129,7 +151,6 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) | |||
| 129 | { | 151 | { |
| 130 | struct ieee80211_local *local = sdata->local; | 152 | struct ieee80211_local *local = sdata->local; |
| 131 | struct sta_info *sta; | 153 | struct sta_info *sta; |
| 132 | u32 changed = 0; | ||
| 133 | u16 ht_opmode; | 154 | u16 ht_opmode; |
| 134 | bool non_ht_sta = false, ht20_sta = false; | 155 | bool non_ht_sta = false, ht20_sta = false; |
| 135 | 156 | ||
| @@ -142,23 +163,19 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) | |||
| 142 | sta->plink_state != NL80211_PLINK_ESTAB) | 163 | sta->plink_state != NL80211_PLINK_ESTAB) |
| 143 | continue; | 164 | continue; |
| 144 | 165 | ||
| 145 | switch (sta->ch_width) { | 166 | if (sta->sta.bandwidth > IEEE80211_STA_RX_BW_20) |
| 146 | case NL80211_CHAN_WIDTH_20_NOHT: | 167 | continue; |
| 147 | mpl_dbg(sdata, | 168 | |
| 148 | "mesh_plink %pM: nonHT sta (%pM) is present\n", | 169 | if (!sta->sta.ht_cap.ht_supported) { |
| 149 | sdata->vif.addr, sta->sta.addr); | 170 | mpl_dbg(sdata, "nonHT sta (%pM) is present\n", |
| 171 | sta->sta.addr); | ||
| 150 | non_ht_sta = true; | 172 | non_ht_sta = true; |
| 151 | goto out; | ||
| 152 | case NL80211_CHAN_WIDTH_20: | ||
| 153 | mpl_dbg(sdata, | ||
| 154 | "mesh_plink %pM: HT20 sta (%pM) is present\n", | ||
| 155 | sdata->vif.addr, sta->sta.addr); | ||
| 156 | ht20_sta = true; | ||
| 157 | default: | ||
| 158 | break; | 173 | break; |
| 159 | } | 174 | } |
| 175 | |||
| 176 | mpl_dbg(sdata, "HT20 sta (%pM) is present\n", sta->sta.addr); | ||
| 177 | ht20_sta = true; | ||
| 160 | } | 178 | } |
| 161 | out: | ||
| 162 | rcu_read_unlock(); | 179 | rcu_read_unlock(); |
| 163 | 180 | ||
| 164 | if (non_ht_sta) | 181 | if (non_ht_sta) |
| @@ -169,16 +186,13 @@ out: | |||
| 169 | else | 186 | else |
| 170 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; | 187 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; |
| 171 | 188 | ||
| 172 | if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) { | 189 | if (sdata->vif.bss_conf.ht_operation_mode == ht_opmode) |
| 173 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; | 190 | return 0; |
| 174 | sdata->u.mesh.mshcfg.ht_opmode = ht_opmode; | ||
| 175 | changed = BSS_CHANGED_HT; | ||
| 176 | mpl_dbg(sdata, | ||
| 177 | "mesh_plink %pM: protection mode changed to %d\n", | ||
| 178 | sdata->vif.addr, ht_opmode); | ||
| 179 | } | ||
| 180 | 191 | ||
| 181 | return changed; | 192 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; |
| 193 | sdata->u.mesh.mshcfg.ht_opmode = ht_opmode; | ||
| 194 | mpl_dbg(sdata, "selected new HT protection mode %d\n", ht_opmode); | ||
| 195 | return BSS_CHANGED_HT; | ||
| 182 | } | 196 | } |
| 183 | 197 | ||
| 184 | /** | 198 | /** |
| @@ -231,8 +245,9 @@ u32 mesh_plink_deactivate(struct sta_info *sta) | |||
| 231 | } | 245 | } |
| 232 | 246 | ||
| 233 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | 247 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, |
| 234 | enum ieee80211_self_protected_actioncode action, | 248 | enum ieee80211_self_protected_actioncode action, |
| 235 | u8 *da, __le16 llid, __le16 plid, __le16 reason) { | 249 | u8 *da, __le16 llid, __le16 plid, __le16 reason) |
| 250 | { | ||
| 236 | struct ieee80211_local *local = sdata->local; | 251 | struct ieee80211_local *local = sdata->local; |
| 237 | struct sk_buff *skb; | 252 | struct sk_buff *skb; |
| 238 | struct ieee80211_tx_info *info; | 253 | struct ieee80211_tx_info *info; |
| @@ -283,13 +298,13 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
| 283 | } | 298 | } |
| 284 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || | 299 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || |
| 285 | ieee80211_add_ext_srates_ie(sdata, skb, true, band) || | 300 | ieee80211_add_ext_srates_ie(sdata, skb, true, band) || |
| 286 | mesh_add_rsn_ie(skb, sdata) || | 301 | mesh_add_rsn_ie(sdata, skb) || |
| 287 | mesh_add_meshid_ie(skb, sdata) || | 302 | mesh_add_meshid_ie(sdata, skb) || |
| 288 | mesh_add_meshconf_ie(skb, sdata)) | 303 | mesh_add_meshconf_ie(sdata, skb)) |
| 289 | goto free; | 304 | goto free; |
| 290 | } else { /* WLAN_SP_MESH_PEERING_CLOSE */ | 305 | } else { /* WLAN_SP_MESH_PEERING_CLOSE */ |
| 291 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | 306 | info->flags |= IEEE80211_TX_CTL_NO_ACK; |
| 292 | if (mesh_add_meshid_ie(skb, sdata)) | 307 | if (mesh_add_meshid_ie(sdata, skb)) |
| 293 | goto free; | 308 | goto free; |
| 294 | } | 309 | } |
| 295 | 310 | ||
| @@ -333,12 +348,12 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
| 333 | } | 348 | } |
| 334 | 349 | ||
| 335 | if (action != WLAN_SP_MESH_PEERING_CLOSE) { | 350 | if (action != WLAN_SP_MESH_PEERING_CLOSE) { |
| 336 | if (mesh_add_ht_cap_ie(skb, sdata) || | 351 | if (mesh_add_ht_cap_ie(sdata, skb) || |
| 337 | mesh_add_ht_oper_ie(skb, sdata)) | 352 | mesh_add_ht_oper_ie(sdata, skb)) |
| 338 | goto free; | 353 | goto free; |
| 339 | } | 354 | } |
| 340 | 355 | ||
| 341 | if (mesh_add_vendor_ies(skb, sdata)) | 356 | if (mesh_add_vendor_ies(sdata, skb)) |
| 342 | goto free; | 357 | goto free; |
| 343 | 358 | ||
| 344 | ieee80211_tx_skb(sdata, skb); | 359 | ieee80211_tx_skb(sdata, skb); |
| @@ -370,24 +385,18 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, | |||
| 370 | if (sta->sta.supp_rates[band] != rates) | 385 | if (sta->sta.supp_rates[band] != rates) |
| 371 | changed |= IEEE80211_RC_SUPP_RATES_CHANGED; | 386 | changed |= IEEE80211_RC_SUPP_RATES_CHANGED; |
| 372 | sta->sta.supp_rates[band] = rates; | 387 | sta->sta.supp_rates[band] = rates; |
| 373 | if (elems->ht_cap_elem && | ||
| 374 | sdata->vif.bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) | ||
| 375 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | ||
| 376 | elems->ht_cap_elem, sta); | ||
| 377 | else | ||
| 378 | memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap)); | ||
| 379 | 388 | ||
| 380 | if (elems->ht_operation) { | 389 | if (ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
| 381 | struct cfg80211_chan_def chandef; | 390 | elems->ht_cap_elem, sta)) |
| 391 | changed |= IEEE80211_RC_BW_CHANGED; | ||
| 382 | 392 | ||
| 383 | if (!(elems->ht_operation->ht_param & | 393 | /* HT peer is operating 20MHz-only */ |
| 384 | IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) | 394 | if (elems->ht_operation && |
| 385 | sta->sta.bandwidth = IEEE80211_STA_RX_BW_20; | 395 | !(elems->ht_operation->ht_param & |
| 386 | ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, | 396 | IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { |
| 387 | elems->ht_operation, &chandef); | 397 | if (sta->sta.bandwidth != IEEE80211_STA_RX_BW_20) |
| 388 | if (sta->ch_width != chandef.width) | ||
| 389 | changed |= IEEE80211_RC_BW_CHANGED; | 398 | changed |= IEEE80211_RC_BW_CHANGED; |
| 390 | sta->ch_width = chandef.width; | 399 | sta->sta.bandwidth = IEEE80211_STA_RX_BW_20; |
| 391 | } | 400 | } |
| 392 | 401 | ||
| 393 | if (insert) | 402 | if (insert) |
| @@ -666,8 +675,9 @@ u32 mesh_plink_block(struct sta_info *sta) | |||
| 666 | } | 675 | } |
| 667 | 676 | ||
| 668 | 677 | ||
| 669 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, | 678 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, |
| 670 | size_t len, struct ieee80211_rx_status *rx_status) | 679 | struct ieee80211_mgmt *mgmt, size_t len, |
| 680 | struct ieee80211_rx_status *rx_status) | ||
| 671 | { | 681 | { |
| 672 | struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; | 682 | struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; |
| 673 | struct ieee802_11_elems elems; | 683 | struct ieee802_11_elems elems; |
| @@ -680,15 +690,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
| 680 | u8 *baseaddr; | 690 | u8 *baseaddr; |
| 681 | u32 changed = 0; | 691 | u32 changed = 0; |
| 682 | __le16 plid, llid, reason; | 692 | __le16 plid, llid, reason; |
| 683 | static const char *mplstates[] = { | ||
| 684 | [NL80211_PLINK_LISTEN] = "LISTEN", | ||
| 685 | [NL80211_PLINK_OPN_SNT] = "OPN-SNT", | ||
| 686 | [NL80211_PLINK_OPN_RCVD] = "OPN-RCVD", | ||
| 687 | [NL80211_PLINK_CNF_RCVD] = "CNF_RCVD", | ||
| 688 | [NL80211_PLINK_ESTAB] = "ESTAB", | ||
| 689 | [NL80211_PLINK_HOLDING] = "HOLDING", | ||
| 690 | [NL80211_PLINK_BLOCKED] = "BLOCKED" | ||
| 691 | }; | ||
| 692 | 693 | ||
| 693 | /* need action_code, aux */ | 694 | /* need action_code, aux */ |
| 694 | if (len < IEEE80211_MIN_ACTION_SIZE + 3) | 695 | if (len < IEEE80211_MIN_ACTION_SIZE + 3) |
| @@ -708,13 +709,15 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
| 708 | baselen += 4; | 709 | baselen += 4; |
| 709 | } | 710 | } |
| 710 | ieee802_11_parse_elems(baseaddr, len - baselen, &elems); | 711 | ieee802_11_parse_elems(baseaddr, len - baselen, &elems); |
| 712 | |||
| 711 | if (!elems.peering) { | 713 | if (!elems.peering) { |
| 712 | mpl_dbg(sdata, | 714 | mpl_dbg(sdata, |
| 713 | "Mesh plink: missing necessary peer link ie\n"); | 715 | "Mesh plink: missing necessary peer link ie\n"); |
| 714 | return; | 716 | return; |
| 715 | } | 717 | } |
| 718 | |||
| 716 | if (elems.rsn_len && | 719 | if (elems.rsn_len && |
| 717 | sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { | 720 | sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { |
| 718 | mpl_dbg(sdata, | 721 | mpl_dbg(sdata, |
| 719 | "Mesh plink: can't establish link with secure peer\n"); | 722 | "Mesh plink: can't establish link with secure peer\n"); |
| 720 | return; | 723 | return; |
| @@ -733,7 +736,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
| 733 | } | 736 | } |
| 734 | 737 | ||
| 735 | if (ftype != WLAN_SP_MESH_PEERING_CLOSE && | 738 | if (ftype != WLAN_SP_MESH_PEERING_CLOSE && |
| 736 | (!elems.mesh_id || !elems.mesh_config)) { | 739 | (!elems.mesh_id || !elems.mesh_config)) { |
| 737 | mpl_dbg(sdata, "Mesh plink: missing necessary ie\n"); | 740 | mpl_dbg(sdata, "Mesh plink: missing necessary ie\n"); |
| 738 | return; | 741 | return; |
| 739 | } | 742 | } |
| @@ -859,11 +862,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
| 859 | } | 862 | } |
| 860 | } | 863 | } |
| 861 | 864 | ||
| 862 | mpl_dbg(sdata, | 865 | mpl_dbg(sdata, "peer %pM in state %s got event %s\n", mgmt->sa, |
| 863 | "Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n", | 866 | mplstates[sta->plink_state], mplevents[event]); |
| 864 | mgmt->sa, mplstates[sta->plink_state], | ||
| 865 | le16_to_cpu(sta->llid), le16_to_cpu(sta->plid), | ||
| 866 | event); | ||
| 867 | reason = 0; | 867 | reason = 0; |
| 868 | spin_lock_bh(&sta->lock); | 868 | spin_lock_bh(&sta->lock); |
| 869 | switch (sta->plink_state) { | 869 | switch (sta->plink_state) { |
diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index aa8d1e437385..05a256b38e24 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c | |||
| @@ -43,7 +43,7 @@ struct sync_method { | |||
| 43 | static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie) | 43 | static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie) |
| 44 | { | 44 | { |
| 45 | return (ie->mesh_config->meshconf_cap & | 45 | return (ie->mesh_config->meshconf_cap & |
| 46 | IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING) != 0; | 46 | IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING) != 0; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata) | 49 | 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, | |||
| 112 | 112 | ||
| 113 | if (elems->mesh_config && mesh_peer_tbtt_adjusting(elems)) { | 113 | if (elems->mesh_config && mesh_peer_tbtt_adjusting(elems)) { |
| 114 | clear_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); | 114 | clear_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); |
| 115 | msync_dbg(sdata, "STA %pM : is adjusting TBTT\n", sta->sta.addr); | 115 | msync_dbg(sdata, "STA %pM : is adjusting TBTT\n", |
| 116 | sta->sta.addr); | ||
| 116 | goto no_sync; | 117 | goto no_sync; |
| 117 | } | 118 | } |
| 118 | 119 | ||
| @@ -129,18 +130,15 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
| 129 | sta->t_offset = t_t - t_r; | 130 | sta->t_offset = t_t - t_r; |
| 130 | 131 | ||
| 131 | if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { | 132 | if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { |
| 132 | s64 t_clockdrift = sta->t_offset_setpoint | 133 | s64 t_clockdrift = sta->t_offset_setpoint - sta->t_offset; |
| 133 | - sta->t_offset; | ||
| 134 | msync_dbg(sdata, | 134 | msync_dbg(sdata, |
| 135 | "STA %pM : sta->t_offset=%lld, sta->t_offset_setpoint=%lld, t_clockdrift=%lld\n", | 135 | "STA %pM : sta->t_offset=%lld, sta->t_offset_setpoint=%lld, t_clockdrift=%lld\n", |
| 136 | sta->sta.addr, | 136 | sta->sta.addr, (long long) sta->t_offset, |
| 137 | (long long) sta->t_offset, | 137 | (long long) sta->t_offset_setpoint, |
| 138 | (long long) | ||
| 139 | sta->t_offset_setpoint, | ||
| 140 | (long long) t_clockdrift); | 138 | (long long) t_clockdrift); |
| 141 | 139 | ||
| 142 | if (t_clockdrift > TOFFSET_MAXIMUM_ADJUSTMENT || | 140 | if (t_clockdrift > TOFFSET_MAXIMUM_ADJUSTMENT || |
| 143 | t_clockdrift < -TOFFSET_MAXIMUM_ADJUSTMENT) { | 141 | t_clockdrift < -TOFFSET_MAXIMUM_ADJUSTMENT) { |
| 144 | msync_dbg(sdata, | 142 | msync_dbg(sdata, |
| 145 | "STA %pM : t_clockdrift=%lld too large, setpoint reset\n", | 143 | "STA %pM : t_clockdrift=%lld too large, setpoint reset\n", |
| 146 | sta->sta.addr, | 144 | sta->sta.addr, |
| @@ -149,15 +147,10 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
| 149 | goto no_sync; | 147 | goto no_sync; |
| 150 | } | 148 | } |
| 151 | 149 | ||
| 152 | rcu_read_unlock(); | ||
| 153 | |||
| 154 | spin_lock_bh(&ifmsh->sync_offset_lock); | 150 | spin_lock_bh(&ifmsh->sync_offset_lock); |
| 155 | if (t_clockdrift > | 151 | if (t_clockdrift > ifmsh->sync_offset_clockdrift_max) |
| 156 | ifmsh->sync_offset_clockdrift_max) | 152 | ifmsh->sync_offset_clockdrift_max = t_clockdrift; |
| 157 | ifmsh->sync_offset_clockdrift_max | ||
| 158 | = t_clockdrift; | ||
| 159 | spin_unlock_bh(&ifmsh->sync_offset_lock); | 153 | spin_unlock_bh(&ifmsh->sync_offset_lock); |
| 160 | |||
| 161 | } else { | 154 | } else { |
| 162 | sta->t_offset_setpoint = sta->t_offset - TOFFSET_SET_MARGIN; | 155 | sta->t_offset_setpoint = sta->t_offset - TOFFSET_SET_MARGIN; |
| 163 | set_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); | 156 | 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, | |||
| 165 | "STA %pM : offset was invalid, sta->t_offset=%lld\n", | 158 | "STA %pM : offset was invalid, sta->t_offset=%lld\n", |
| 166 | sta->sta.addr, | 159 | sta->sta.addr, |
| 167 | (long long) sta->t_offset); | 160 | (long long) sta->t_offset); |
| 168 | rcu_read_unlock(); | ||
| 169 | } | 161 | } |
| 170 | return; | ||
| 171 | 162 | ||
| 172 | no_sync: | 163 | no_sync: |
| 173 | rcu_read_unlock(); | 164 | rcu_read_unlock(); |
| @@ -177,14 +168,12 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata) | |||
| 177 | { | 168 | { |
| 178 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 169 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
| 179 | 170 | ||
| 180 | WARN_ON(ifmsh->mesh_sp_id | 171 | WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); |
| 181 | != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); | ||
| 182 | BUG_ON(!rcu_read_lock_held()); | 172 | BUG_ON(!rcu_read_lock_held()); |
| 183 | 173 | ||
| 184 | spin_lock_bh(&ifmsh->sync_offset_lock); | 174 | spin_lock_bh(&ifmsh->sync_offset_lock); |
| 185 | 175 | ||
| 186 | if (ifmsh->sync_offset_clockdrift_max > | 176 | if (ifmsh->sync_offset_clockdrift_max > TOFFSET_MINIMUM_ADJUSTMENT) { |
| 187 | TOFFSET_MINIMUM_ADJUSTMENT) { | ||
| 188 | /* Since ajusting the tsf here would | 177 | /* Since ajusting the tsf here would |
| 189 | * require a possibly blocking call | 178 | * require a possibly blocking call |
| 190 | * to the driver tsf setter, we punt | 179 | * to the driver tsf setter, we punt |
| @@ -193,8 +182,7 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata) | |||
| 193 | msync_dbg(sdata, | 182 | msync_dbg(sdata, |
| 194 | "TBTT : kicking off TBTT adjustment with clockdrift_max=%lld\n", | 183 | "TBTT : kicking off TBTT adjustment with clockdrift_max=%lld\n", |
| 195 | ifmsh->sync_offset_clockdrift_max); | 184 | ifmsh->sync_offset_clockdrift_max); |
| 196 | set_bit(MESH_WORK_DRIFT_ADJUST, | 185 | set_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags); |
| 197 | &ifmsh->wrkq_flags); | ||
| 198 | 186 | ||
| 199 | ifmsh->adjusting_tbtt = true; | 187 | ifmsh->adjusting_tbtt = true; |
| 200 | } else { | 188 | } else { |
| @@ -220,14 +208,11 @@ static const struct sync_method sync_methods[] = { | |||
| 220 | 208 | ||
| 221 | const struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method) | 209 | const struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method) |
| 222 | { | 210 | { |
| 223 | const struct ieee80211_mesh_sync_ops *ops = NULL; | 211 | int i; |
| 224 | u8 i; | ||
| 225 | 212 | ||
| 226 | for (i = 0 ; i < ARRAY_SIZE(sync_methods); ++i) { | 213 | for (i = 0 ; i < ARRAY_SIZE(sync_methods); ++i) { |
| 227 | if (sync_methods[i].method == method) { | 214 | if (sync_methods[i].method == method) |
| 228 | ops = &sync_methods[i].ops; | 215 | return &sync_methods[i].ops; |
| 229 | break; | ||
| 230 | } | ||
| 231 | } | 216 | } |
| 232 | return ops; | 217 | return NULL; |
| 233 | } | 218 | } |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3acb70b73e22..bb73ed2d20b9 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
| @@ -2027,7 +2027,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
| 2027 | /* frame is in RMC, don't forward */ | 2027 | /* frame is in RMC, don't forward */ |
| 2028 | if (ieee80211_is_data(hdr->frame_control) && | 2028 | if (ieee80211_is_data(hdr->frame_control) && |
| 2029 | is_multicast_ether_addr(hdr->addr1) && | 2029 | is_multicast_ether_addr(hdr->addr1) && |
| 2030 | mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) | 2030 | mesh_rmc_check(rx->sdata, hdr->addr3, mesh_hdr)) |
| 2031 | return RX_DROP_MONITOR; | 2031 | return RX_DROP_MONITOR; |
| 2032 | 2032 | ||
| 2033 | if (!ieee80211_is_data(hdr->frame_control) || | 2033 | if (!ieee80211_is_data(hdr->frame_control) || |
| @@ -2054,9 +2054,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
| 2054 | } | 2054 | } |
| 2055 | 2055 | ||
| 2056 | rcu_read_lock(); | 2056 | rcu_read_lock(); |
| 2057 | mppath = mpp_path_lookup(proxied_addr, sdata); | 2057 | mppath = mpp_path_lookup(sdata, proxied_addr); |
| 2058 | if (!mppath) { | 2058 | if (!mppath) { |
| 2059 | mpp_path_add(proxied_addr, mpp_addr, sdata); | 2059 | mpp_path_add(sdata, proxied_addr, mpp_addr); |
| 2060 | } else { | 2060 | } else { |
| 2061 | spin_lock_bh(&mppath->state_lock); | 2061 | spin_lock_bh(&mppath->state_lock); |
| 2062 | if (!ether_addr_equal(mppath->mpp, mpp_addr)) | 2062 | if (!ether_addr_equal(mppath->mpp, mpp_addr)) |
| @@ -2104,13 +2104,13 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
| 2104 | memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); | 2104 | memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); |
| 2105 | /* update power mode indication when forwarding */ | 2105 | /* update power mode indication when forwarding */ |
| 2106 | ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr); | 2106 | ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr); |
| 2107 | } else if (!mesh_nexthop_lookup(fwd_skb, sdata)) { | 2107 | } else if (!mesh_nexthop_lookup(sdata, fwd_skb)) { |
| 2108 | /* mesh power mode flags updated in mesh_nexthop_lookup */ | 2108 | /* mesh power mode flags updated in mesh_nexthop_lookup */ |
| 2109 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast); | 2109 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast); |
| 2110 | } else { | 2110 | } else { |
| 2111 | /* unable to resolve next hop */ | 2111 | /* unable to resolve next hop */ |
| 2112 | mesh_path_error_tx(ifmsh->mshcfg.element_ttl, fwd_hdr->addr3, | 2112 | mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl, |
| 2113 | 0, reason, fwd_hdr->addr2, sdata); | 2113 | fwd_hdr->addr3, 0, reason, fwd_hdr->addr2); |
| 2114 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route); | 2114 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route); |
| 2115 | kfree_skb(fwd_skb); | 2115 | kfree_skb(fwd_skb); |
| 2116 | return RX_DROP_MONITOR; | 2116 | return RX_DROP_MONITOR; |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 63dfdb5e91da..4947341a2a82 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
| @@ -285,7 +285,6 @@ struct sta_ampdu_mlme { | |||
| 285 | * @t_offset: timing offset relative to this host | 285 | * @t_offset: timing offset relative to this host |
| 286 | * @t_offset_setpoint: reference timing offset of this sta to be used when | 286 | * @t_offset_setpoint: reference timing offset of this sta to be used when |
| 287 | * calculating clockdrift | 287 | * calculating clockdrift |
| 288 | * @ch_width: peer's channel width | ||
| 289 | * @local_pm: local link-specific power save mode | 288 | * @local_pm: local link-specific power save mode |
| 290 | * @peer_pm: peer-specific power save mode towards local STA | 289 | * @peer_pm: peer-specific power save mode towards local STA |
| 291 | * @nonpeer_pm: STA power save mode towards non-peer neighbors | 290 | * @nonpeer_pm: STA power save mode towards non-peer neighbors |
| @@ -386,7 +385,6 @@ struct sta_info { | |||
| 386 | struct timer_list plink_timer; | 385 | struct timer_list plink_timer; |
| 387 | s64 t_offset; | 386 | s64 t_offset; |
| 388 | s64 t_offset_setpoint; | 387 | s64 t_offset_setpoint; |
| 389 | enum nl80211_chan_width ch_width; | ||
| 390 | /* mesh power save */ | 388 | /* mesh power save */ |
| 391 | enum nl80211_mesh_power_mode local_pm; | 389 | enum nl80211_mesh_power_mode local_pm; |
| 392 | enum nl80211_mesh_power_mode peer_pm; | 390 | enum nl80211_mesh_power_mode peer_pm; |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 1183c4a4fee5..3d7cd2a0582f 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
| @@ -479,7 +479,7 @@ TRACE_EVENT(drv_set_tim, | |||
| 479 | 479 | ||
| 480 | TP_printk( | 480 | TP_printk( |
| 481 | LOCAL_PR_FMT STA_PR_FMT " set:%d", | 481 | LOCAL_PR_FMT STA_PR_FMT " set:%d", |
| 482 | LOCAL_PR_ARG, STA_PR_FMT, __entry->set | 482 | LOCAL_PR_ARG, STA_PR_ARG, __entry->set |
| 483 | ) | 483 | ) |
| 484 | ); | 484 | ); |
| 485 | 485 | ||
| @@ -1684,7 +1684,7 @@ TRACE_EVENT(api_sta_block_awake, | |||
| 1684 | 1684 | ||
| 1685 | TP_printk( | 1685 | TP_printk( |
| 1686 | LOCAL_PR_FMT STA_PR_FMT " block:%d", | 1686 | LOCAL_PR_FMT STA_PR_FMT " block:%d", |
| 1687 | LOCAL_PR_ARG, STA_PR_FMT, __entry->block | 1687 | LOCAL_PR_ARG, STA_PR_ARG, __entry->block |
| 1688 | ) | 1688 | ) |
| 1689 | ); | 1689 | ); |
| 1690 | 1690 | ||
| @@ -1782,7 +1782,7 @@ TRACE_EVENT(api_eosp, | |||
| 1782 | 1782 | ||
| 1783 | TP_printk( | 1783 | TP_printk( |
| 1784 | LOCAL_PR_FMT STA_PR_FMT, | 1784 | LOCAL_PR_FMT STA_PR_FMT, |
| 1785 | LOCAL_PR_ARG, STA_PR_FMT | 1785 | LOCAL_PR_ARG, STA_PR_ARG |
| 1786 | ) | 1786 | ) |
| 1787 | ); | 1787 | ); |
| 1788 | 1788 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index fe644f91ae05..5b9602b62405 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
| @@ -1495,7 +1495,7 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | |||
| 1495 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1495 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
| 1496 | if (ieee80211_is_data(hdr->frame_control) && | 1496 | if (ieee80211_is_data(hdr->frame_control) && |
| 1497 | is_unicast_ether_addr(hdr->addr1)) { | 1497 | is_unicast_ether_addr(hdr->addr1)) { |
| 1498 | if (mesh_nexthop_resolve(skb, sdata)) | 1498 | if (mesh_nexthop_resolve(sdata, skb)) |
| 1499 | return; /* skb queued: don't free */ | 1499 | return; /* skb queued: don't free */ |
| 1500 | } else { | 1500 | } else { |
| 1501 | ieee80211_mps_set_frame_flags(sdata, NULL, hdr); | 1501 | ieee80211_mps_set_frame_flags(sdata, NULL, hdr); |
| @@ -1844,9 +1844,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
| 1844 | } | 1844 | } |
| 1845 | 1845 | ||
| 1846 | if (!is_multicast_ether_addr(skb->data)) { | 1846 | if (!is_multicast_ether_addr(skb->data)) { |
| 1847 | mpath = mesh_path_lookup(skb->data, sdata); | 1847 | mpath = mesh_path_lookup(sdata, skb->data); |
| 1848 | if (!mpath) | 1848 | if (!mpath) |
| 1849 | mppath = mpp_path_lookup(skb->data, sdata); | 1849 | mppath = mpp_path_lookup(sdata, skb->data); |
| 1850 | } | 1850 | } |
| 1851 | 1851 | ||
| 1852 | /* | 1852 | /* |
| @@ -1859,8 +1859,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
| 1859 | !(mppath && !ether_addr_equal(mppath->mpp, skb->data))) { | 1859 | !(mppath && !ether_addr_equal(mppath->mpp, skb->data))) { |
| 1860 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | 1860 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
| 1861 | skb->data, skb->data + ETH_ALEN); | 1861 | skb->data, skb->data + ETH_ALEN); |
| 1862 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, | 1862 | meshhdrlen = ieee80211_new_mesh_header(sdata, &mesh_hdr, |
| 1863 | sdata, NULL, NULL); | 1863 | NULL, NULL); |
| 1864 | } else { | 1864 | } else { |
| 1865 | /* DS -> MBSS (802.11-2012 13.11.3.3). | 1865 | /* DS -> MBSS (802.11-2012 13.11.3.3). |
| 1866 | * For unicast with unknown forwarding information, | 1866 | * For unicast with unknown forwarding information, |
| @@ -1879,18 +1879,14 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
| 1879 | mesh_da, sdata->vif.addr); | 1879 | mesh_da, sdata->vif.addr); |
| 1880 | if (is_multicast_ether_addr(mesh_da)) | 1880 | if (is_multicast_ether_addr(mesh_da)) |
| 1881 | /* DA TA mSA AE:SA */ | 1881 | /* DA TA mSA AE:SA */ |
| 1882 | meshhdrlen = | 1882 | meshhdrlen = ieee80211_new_mesh_header( |
| 1883 | ieee80211_new_mesh_header(&mesh_hdr, | 1883 | sdata, &mesh_hdr, |
| 1884 | sdata, | 1884 | skb->data + ETH_ALEN, NULL); |
| 1885 | skb->data + ETH_ALEN, | ||
| 1886 | NULL); | ||
| 1887 | else | 1885 | else |
| 1888 | /* RA TA mDA mSA AE:DA SA */ | 1886 | /* RA TA mDA mSA AE:DA SA */ |
| 1889 | meshhdrlen = | 1887 | meshhdrlen = ieee80211_new_mesh_header( |
| 1890 | ieee80211_new_mesh_header(&mesh_hdr, | 1888 | sdata, &mesh_hdr, skb->data, |
| 1891 | sdata, | 1889 | skb->data + ETH_ALEN); |
| 1892 | skb->data, | ||
| 1893 | skb->data + ETH_ALEN); | ||
| 1894 | 1890 | ||
| 1895 | } | 1891 | } |
| 1896 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 1892 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 580ffeaef3d5..35545ccc30fd 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -3418,19 +3418,10 @@ nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = { | |||
| 3418 | static int nl80211_set_station_tdls(struct genl_info *info, | 3418 | static int nl80211_set_station_tdls(struct genl_info *info, |
| 3419 | struct station_parameters *params) | 3419 | struct station_parameters *params) |
| 3420 | { | 3420 | { |
| 3421 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
| 3422 | struct nlattr *tb[NL80211_STA_WME_MAX + 1]; | 3421 | struct nlattr *tb[NL80211_STA_WME_MAX + 1]; |
| 3423 | struct nlattr *nla; | 3422 | struct nlattr *nla; |
| 3424 | int err; | 3423 | int err; |
| 3425 | 3424 | ||
| 3426 | /* Can only set if TDLS ... */ | ||
| 3427 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS)) | ||
| 3428 | return -EOPNOTSUPP; | ||
| 3429 | |||
| 3430 | /* ... with external setup is supported */ | ||
| 3431 | if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)) | ||
| 3432 | return -EOPNOTSUPP; | ||
| 3433 | |||
| 3434 | /* Dummy STA entry gets updated once the peer capabilities are known */ | 3425 | /* Dummy STA entry gets updated once the peer capabilities are known */ |
| 3435 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) | 3426 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) |
| 3436 | params->ht_capa = | 3427 | params->ht_capa = |
