Blame view
net/mac80211/mesh.c
18.8 KB
2e3c87368 mac80211: support... |
1 |
/* |
264d9b7d8 mac80211: update ... |
2 |
* Copyright (c) 2008, 2009 open80211s Ltd. |
2e3c87368 mac80211: support... |
3 4 5 6 7 8 9 |
* Authors: Luis Carlos Cobo <luisca@cozybit.com> * Javier Cardona <javier@cozybit.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ |
5a0e3ad6a include cleanup: ... |
10 |
#include <linux/slab.h> |
51ceddade mac80211: use 4-b... |
11 |
#include <asm/unaligned.h> |
2e3c87368 mac80211: support... |
12 13 |
#include "ieee80211_i.h" #include "mesh.h" |
472dbc45d mac80211: split o... |
14 15 |
#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) |
e304bfd30 mac80211: impleme... |
16 |
#define IEEE80211_MESH_RANN_INTERVAL (1 * HZ) |
472dbc45d mac80211: split o... |
17 |
|
3491707a0 mac80211: update ... |
18 19 |
#define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01 #define MESHCONF_CAPAB_FORWARDING 0x08 |
2e3c87368 mac80211: support... |
20 |
|
5bb644a0f mac80211: cancel/... |
21 22 |
#define TMR_RUNNING_HK 0 #define TMR_RUNNING_MP 1 |
e304bfd30 mac80211: impleme... |
23 |
#define TMR_RUNNING_MPR 2 |
5bb644a0f mac80211: cancel/... |
24 |
|
2e3c87368 mac80211: support... |
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
int mesh_allocated; static struct kmem_cache *rm_cache; void ieee80211s_init(void) { mesh_pathtbl_init(); mesh_allocated = 1; rm_cache = kmem_cache_create("mesh_rmc", sizeof(struct rmc_entry), 0, 0, NULL); } void ieee80211s_stop(void) { mesh_pathtbl_unregister(); kmem_cache_destroy(rm_cache); } |
472dbc45d mac80211: split o... |
41 42 43 44 45 |
static void ieee80211_mesh_housekeeping_timer(unsigned long data) { struct ieee80211_sub_if_data *sdata = (void *) data; struct ieee80211_local *local = sdata->local; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
6b9ac4425 mesh: use set_bit... |
46 |
set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); |
5bb644a0f mac80211: cancel/... |
47 48 49 50 51 |
if (local->quiescing) { set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); return; } |
64592c8fc mac80211: use com... |
52 |
ieee80211_queue_work(&local->hw, &sdata->work); |
472dbc45d mac80211: split o... |
53 |
} |
2e3c87368 mac80211: support... |
54 55 56 57 |
/** * mesh_matches_local - check if the config of a mesh point matches ours * * @ie: information elements of a management frame from the mesh peer |
f698d856f replace net_devic... |
58 |
* @sdata: local mesh subif |
2e3c87368 mac80211: support... |
59 60 61 62 |
* * This function checks if the mesh configuration of a mesh point matches the * local mesh configuration, i.e. if both nodes belong to the same mesh network. */ |
f698d856f replace net_devic... |
63 |
bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) |
2e3c87368 mac80211: support... |
64 |
{ |
472dbc45d mac80211: split o... |
65 |
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
2e3c87368 mac80211: support... |
66 |
|
2e3c87368 mac80211: support... |
67 68 69 70 71 72 73 74 75 76 |
/* * As support for each feature is added, check for matching * - On mesh config capabilities * - Power Save Support En * - Sync support enabled * - Sync support active * - Sync support required from peer * - MDA enabled * - Power management control on fc */ |
472dbc45d mac80211: split o... |
77 78 |
if (ifmsh->mesh_id_len == ie->mesh_id_len && memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && |
136cfa286 mac80211: use a s... |
79 80 81 82 83 |
(ifmsh->mesh_pp_id == ie->mesh_config->meshconf_psel) && (ifmsh->mesh_pm_id == ie->mesh_config->meshconf_pmetric) && (ifmsh->mesh_cc_id == ie->mesh_config->meshconf_congest) && (ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) && (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth)) |
2e3c87368 mac80211: support... |
84 85 86 87 88 89 90 91 92 |
return true; return false; } /** * mesh_peer_accepts_plinks - check if an mp is willing to establish peer links * * @ie: information elements of a management frame from the mesh peer |
2e3c87368 mac80211: support... |
93 |
*/ |
f698d856f replace net_devic... |
94 |
bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) |
2e3c87368 mac80211: support... |
95 |
{ |
136cfa286 mac80211: use a s... |
96 |
return (ie->mesh_config->meshconf_cap & |
3491707a0 mac80211: update ... |
97 |
MESHCONF_CAPAB_ACCEPT_PLINKS) != 0; |
2e3c87368 mac80211: support... |
98 99 100 101 102 |
} /** * mesh_accept_plinks_update: update accepting_plink in local mesh beacons * |
d0709a651 mac80211: RCU-ify... |
103 |
* @sdata: mesh interface in which mesh beacons are going to be updated |
2e3c87368 mac80211: support... |
104 |
*/ |
d0709a651 mac80211: RCU-ify... |
105 |
void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) |
2e3c87368 mac80211: support... |
106 |
{ |
2e3c87368 mac80211: support... |
107 108 109 110 |
bool free_plinks; /* In case mesh_plink_free_count > 0 and mesh_plinktbl_capacity == 0, * the mesh interface might be able to establish plinks with peers that |
b4e08ea14 mac80211: add PLI... |
111 112 113 |
* are already on the table but are not on PLINK_ESTAB state. However, * in general the mesh interface is not accepting peer link requests * from new peers, and that must be reflected in the beacon |
2e3c87368 mac80211: support... |
114 115 |
*/ free_plinks = mesh_plink_availables(sdata); |
472dbc45d mac80211: split o... |
116 117 |
if (free_plinks != sdata->u.mesh.accepting_plinks) ieee80211_mesh_housekeeping_timer((unsigned long) sdata); |
2e3c87368 mac80211: support... |
118 |
} |
f698d856f replace net_devic... |
119 |
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) |
2e3c87368 mac80211: support... |
120 |
{ |
2e3c87368 mac80211: support... |
121 |
int i; |
472dbc45d mac80211: split o... |
122 123 |
sdata->u.mesh.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); if (!sdata->u.mesh.rmc) |
2e3c87368 mac80211: support... |
124 |
return -ENOMEM; |
472dbc45d mac80211: split o... |
125 |
sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1; |
2e3c87368 mac80211: support... |
126 |
for (i = 0; i < RMC_BUCKETS; i++) |
472dbc45d mac80211: split o... |
127 |
INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list); |
2e3c87368 mac80211: support... |
128 129 |
return 0; } |
f698d856f replace net_devic... |
130 |
void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) |
2e3c87368 mac80211: support... |
131 |
{ |
472dbc45d mac80211: split o... |
132 |
struct mesh_rmc *rmc = sdata->u.mesh.rmc; |
2e3c87368 mac80211: support... |
133 134 |
struct rmc_entry *p, *n; int i; |
472dbc45d mac80211: split o... |
135 |
if (!sdata->u.mesh.rmc) |
2e3c87368 mac80211: support... |
136 137 138 139 140 141 142 143 144 |
return; for (i = 0; i < RMC_BUCKETS; i++) list_for_each_entry_safe(p, n, &rmc->bucket[i].list, list) { list_del(&p->list); kmem_cache_free(rm_cache, p); } kfree(rmc); |
472dbc45d mac80211: split o... |
145 |
sdata->u.mesh.rmc = NULL; |
2e3c87368 mac80211: support... |
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
} /** * mesh_rmc_check - Check frame in recent multicast cache and add if absent. * * @sa: source address * @mesh_hdr: mesh_header * * Returns: 0 if the frame is not in the cache, nonzero otherwise. * * Checks using the source address and the mesh sequence number if we have * received this frame lately. If the frame is not in the cache, it is added to * it. */ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, |
f698d856f replace net_devic... |
161 |
struct ieee80211_sub_if_data *sdata) |
2e3c87368 mac80211: support... |
162 |
{ |
472dbc45d mac80211: split o... |
163 |
struct mesh_rmc *rmc = sdata->u.mesh.rmc; |
2e3c87368 mac80211: support... |
164 165 166 167 168 169 |
u32 seqnum = 0; int entries = 0; u8 idx; struct rmc_entry *p, *n; /* Don't care about endianness since only match matters */ |
51ceddade mac80211: use 4-b... |
170 171 |
memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum)); idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask; |
2e3c87368 mac80211: support... |
172 173 174 175 176 177 178 |
list_for_each_entry_safe(p, n, &rmc->bucket[idx].list, list) { ++entries; if (time_after(jiffies, p->exp_time) || (entries == RMC_QUEUE_MAX_LEN)) { list_del(&p->list); kmem_cache_free(rm_cache, p); --entries; |
f64f9e719 net: Move && and ... |
179 180 |
} else if ((seqnum == p->seqnum) && (memcmp(sa, p->sa, ETH_ALEN) == 0)) |
2e3c87368 mac80211: support... |
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
return -1; } p = kmem_cache_alloc(rm_cache, GFP_ATOMIC); if (!p) { printk(KERN_DEBUG "o11s: could not allocate RMC entry "); return 0; } p->seqnum = seqnum; p->exp_time = jiffies + RMC_TIMEOUT; memcpy(p->sa, sa, ETH_ALEN); list_add(&p->list, &rmc->bucket[idx].list); return 0; } |
f698d856f replace net_devic... |
196 |
void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) |
2e3c87368 mac80211: support... |
197 |
{ |
f698d856f replace net_devic... |
198 |
struct ieee80211_local *local = sdata->local; |
2e3c87368 mac80211: support... |
199 200 201 |
struct ieee80211_supported_band *sband; u8 *pos; int len, i, rate; |
8f2fda959 mac80211: impleme... |
202 |
u8 neighbors; |
2e3c87368 mac80211: support... |
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; len = sband->n_bitrates; if (len > 8) len = 8; pos = skb_put(skb, len + 2); *pos++ = WLAN_EID_SUPP_RATES; *pos++ = len; for (i = 0; i < len; i++) { rate = sband->bitrates[i].bitrate; *pos++ = (u8) (rate / 5); } if (sband->n_bitrates > len) { pos = skb_put(skb, sband->n_bitrates - len + 2); *pos++ = WLAN_EID_EXT_SUPP_RATES; *pos++ = sband->n_bitrates - len; for (i = len; i < sband->n_bitrates; i++) { rate = sband->bitrates[i].bitrate; *pos++ = (u8) (rate / 5); } } |
be125c60e mac80211: add the... |
225 226 227 228 229 230 |
if (sband->band == IEEE80211_BAND_2GHZ) { pos = skb_put(skb, 2 + 1); *pos++ = WLAN_EID_DS_PARAMS; *pos++ = 1; *pos++ = ieee80211_frequency_to_channel(local->hw.conf.channel->center_freq); } |
472dbc45d mac80211: split o... |
231 |
pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len); |
2e3c87368 mac80211: support... |
232 |
*pos++ = WLAN_EID_MESH_ID; |
472dbc45d mac80211: split o... |
233 234 235 |
*pos++ = sdata->u.mesh.mesh_id_len; if (sdata->u.mesh.mesh_id_len) memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len); |
2e3c87368 mac80211: support... |
236 |
|
136cfa286 mac80211: use a s... |
237 |
pos = skb_put(skb, 2 + sizeof(struct ieee80211_meshconf_ie)); |
2e3c87368 mac80211: support... |
238 |
*pos++ = WLAN_EID_MESH_CONFIG; |
136cfa286 mac80211: use a s... |
239 |
*pos++ = sizeof(struct ieee80211_meshconf_ie); |
2e3c87368 mac80211: support... |
240 241 |
/* Active path selection protocol ID */ |
3491707a0 mac80211: update ... |
242 |
*pos++ = sdata->u.mesh.mesh_pp_id; |
2e3c87368 mac80211: support... |
243 244 |
/* Active path selection metric ID */ |
3491707a0 mac80211: update ... |
245 |
*pos++ = sdata->u.mesh.mesh_pm_id; |
2e3c87368 mac80211: support... |
246 247 |
/* Congestion control mode identifier */ |
3491707a0 mac80211: update ... |
248 |
*pos++ = sdata->u.mesh.mesh_cc_id; |
2e3c87368 mac80211: support... |
249 |
|
9e03fdfd0 mac80211: Update ... |
250 |
/* Synchronization protocol identifier */ |
3491707a0 mac80211: update ... |
251 |
*pos++ = sdata->u.mesh.mesh_sp_id; |
2e3c87368 mac80211: support... |
252 |
|
9e03fdfd0 mac80211: Update ... |
253 |
/* Authentication Protocol identifier */ |
3491707a0 mac80211: update ... |
254 |
*pos++ = sdata->u.mesh.mesh_auth_id; |
9e03fdfd0 mac80211: Update ... |
255 |
|
8f2fda959 mac80211: impleme... |
256 257 258 259 260 |
/* Mesh Formation Info - number of neighbors */ neighbors = atomic_read(&sdata->u.mesh.mshstats.estab_plinks); /* Number of neighbor mesh STAs or 15 whichever is smaller */ neighbors = (neighbors > 15) ? 15 : neighbors; *pos++ = neighbors << 1; |
9e03fdfd0 mac80211: Update ... |
261 |
|
2e3c87368 mac80211: support... |
262 |
/* Mesh capability */ |
472dbc45d mac80211: split o... |
263 |
sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata); |
3491707a0 mac80211: update ... |
264 265 266 |
*pos = MESHCONF_CAPAB_FORWARDING; *pos++ |= sdata->u.mesh.accepting_plinks ? MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; |
2e3c87368 mac80211: support... |
267 |
*pos++ = 0x00; |
c80d545da mac80211: Let use... |
268 |
|
581a8b0fe nl80211: rename N... |
269 270 271 |
if (sdata->u.mesh.ie) { int len = sdata->u.mesh.ie_len; const u8 *data = sdata->u.mesh.ie; |
c80d545da mac80211: Let use... |
272 273 274 |
if (skb_tailroom(skb) > len) memcpy(skb_put(skb, len), data, len); } |
2e3c87368 mac80211: support... |
275 |
} |
2e3c87368 mac80211: support... |
276 277 278 279 280 |
static void ieee80211_mesh_path_timer(unsigned long data) { struct ieee80211_sub_if_data *sdata = (struct ieee80211_sub_if_data *) data; |
472dbc45d mac80211: split o... |
281 |
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
133b82263 mac80211: make ma... |
282 |
struct ieee80211_local *local = sdata->local; |
2e3c87368 mac80211: support... |
283 |
|
5bb644a0f mac80211: cancel/... |
284 285 286 287 |
if (local->quiescing) { set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); return; } |
64592c8fc mac80211: use com... |
288 |
ieee80211_queue_work(&local->hw, &sdata->work); |
2e3c87368 mac80211: support... |
289 |
} |
e304bfd30 mac80211: impleme... |
290 291 292 293 294 295 296 297 298 299 300 301 302 |
static void ieee80211_mesh_path_root_timer(unsigned long data) { struct ieee80211_sub_if_data *sdata = (struct ieee80211_sub_if_data *) data; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_local *local = sdata->local; set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags); if (local->quiescing) { set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running); return; } |
64592c8fc mac80211: use com... |
303 |
ieee80211_queue_work(&local->hw, &sdata->work); |
e304bfd30 mac80211: impleme... |
304 |
} |
63c5723bc mac80211: add nl8... |
305 306 307 308 309 310 311 312 313 314 |
void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh) { if (ifmsh->mshcfg.dot11MeshHWMPRootMode) set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags); else { clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags); /* stop running timer */ del_timer_sync(&ifmsh->mesh_path_root_timer); } } |
902acc789 mac80211: clean u... |
315 |
/** |
3c5772a52 mac80211: Use 3-a... |
316 317 318 319 320 321 322 323 324 |
* ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame * @hdr: 802.11 frame header * @fc: frame control field * @meshda: destination address in the mesh * @meshsa: source address address in the mesh. Same as TA, as frame is * locally originated. * * Return the length of the 802.11 (does not include a mesh control header) */ |
15ff63653 mac80211: use fix... |
325 326 327 |
int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, const u8 *meshda, const u8 *meshsa) { |
3c5772a52 mac80211: Use 3-a... |
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 |
if (is_multicast_ether_addr(meshda)) { *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); /* DA TA SA */ memcpy(hdr->addr1, meshda, ETH_ALEN); memcpy(hdr->addr2, meshsa, ETH_ALEN); memcpy(hdr->addr3, meshsa, ETH_ALEN); return 24; } else { *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); /* RA TA DA SA */ memset(hdr->addr1, 0, ETH_ALEN); /* RA is resolved later */ memcpy(hdr->addr2, meshsa, ETH_ALEN); memcpy(hdr->addr3, meshda, ETH_ALEN); memcpy(hdr->addr4, meshsa, ETH_ALEN); return 30; } } /** |
902acc789 mac80211: clean u... |
348 349 350 |
* ieee80211_new_mesh_header - create a new mesh header * @meshhdr: uninitialized mesh header * @sdata: mesh interface to be used |
61ad53945 mac80211: Remove ... |
351 352 353 354 355 |
* @addr4or5: 1st address in the ae header, which may correspond to address 4 * (if addr6 is NULL) or address 5 (if addr6 is present). It may * be NULL. * @addr6: 2nd address in the ae header, which corresponds to addr6 of the * mesh frame |
902acc789 mac80211: clean u... |
356 357 358 359 |
* * Return the header length. */ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, |
61ad53945 mac80211: Remove ... |
360 361 |
struct ieee80211_sub_if_data *sdata, char *addr4or5, char *addr6) |
902acc789 mac80211: clean u... |
362 |
{ |
3c5772a52 mac80211: Use 3-a... |
363 |
int aelen = 0; |
61ad53945 mac80211: Remove ... |
364 |
BUG_ON(!addr4or5 && addr6); |
0c3cee72a net/mac80211: Cor... |
365 |
memset(meshhdr, 0, sizeof(*meshhdr)); |
472dbc45d mac80211: split o... |
366 367 368 |
meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); sdata->u.mesh.mesh_seqnum++; |
61ad53945 mac80211: Remove ... |
369 |
if (addr4or5 && !addr6) { |
3c5772a52 mac80211: Use 3-a... |
370 371 |
meshhdr->flags |= MESH_FLAGS_AE_A4; aelen += ETH_ALEN; |
61ad53945 mac80211: Remove ... |
372 373 |
memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); } else if (addr4or5 && addr6) { |
3c5772a52 mac80211: Use 3-a... |
374 375 |
meshhdr->flags |= MESH_FLAGS_AE_A5_A6; aelen += 2 * ETH_ALEN; |
61ad53945 mac80211: Remove ... |
376 377 |
memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); memcpy(meshhdr->eaddr2, addr6, ETH_ALEN); |
3c5772a52 mac80211: Use 3-a... |
378 379 |
} return 6 + aelen; |
902acc789 mac80211: clean u... |
380 |
} |
472dbc45d mac80211: split o... |
381 382 383 384 385 386 387 388 |
static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_mesh *ifmsh) { bool free_plinks; #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: running mesh housekeeping ", |
47846c9b0 mac80211: reduce ... |
389 |
sdata->name); |
472dbc45d mac80211: split o... |
390 391 392 393 394 395 396 |
#endif ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); mesh_path_expire(sdata); free_plinks = mesh_plink_availables(sdata); if (free_plinks != sdata->u.mesh.accepting_plinks) |
2d0ddec5b mac80211: unify c... |
397 |
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); |
472dbc45d mac80211: split o... |
398 |
|
472dbc45d mac80211: split o... |
399 400 401 |
mod_timer(&ifmsh->housekeeping_timer, round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); } |
e304bfd30 mac80211: impleme... |
402 403 404 405 406 407 408 409 |
static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; mesh_path_tx_root_frame(sdata); mod_timer(&ifmsh->mesh_path_root_timer, round_jiffies(jiffies + IEEE80211_MESH_RANN_INTERVAL)); } |
5bb644a0f mac80211: cancel/... |
410 411 412 413 |
#ifdef CONFIG_PM void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
5bb644a0f mac80211: cancel/... |
414 415 416 417 418 419 |
/* use atomic bitops in case both timers fire at the same time */ if (del_timer_sync(&ifmsh->housekeeping_timer)) set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); if (del_timer_sync(&ifmsh->mesh_path_timer)) set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); |
e304bfd30 mac80211: impleme... |
420 421 |
if (del_timer_sync(&ifmsh->mesh_path_root_timer)) set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running); |
5bb644a0f mac80211: cancel/... |
422 423 424 425 426 427 428 429 430 431 |
} void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; if (test_and_clear_bit(TMR_RUNNING_HK, &ifmsh->timers_running)) add_timer(&ifmsh->housekeeping_timer); if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running)) add_timer(&ifmsh->mesh_path_timer); |
e304bfd30 mac80211: impleme... |
432 433 |
if (test_and_clear_bit(TMR_RUNNING_MPR, &ifmsh->timers_running)) add_timer(&ifmsh->mesh_path_root_timer); |
63c5723bc mac80211: add nl8... |
434 |
ieee80211_mesh_root_setup(ifmsh); |
5bb644a0f mac80211: cancel/... |
435 436 |
} #endif |
472dbc45d mac80211: split o... |
437 438 439 440 441 |
void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_local *local = sdata->local; |
09b174702 mac80211: move me... |
442 443 444 445 |
local->fif_other_bss++; /* mesh ifaces must set allmulti to forward mcast traffic */ atomic_inc(&local->iff_allmultis); ieee80211_configure_filter(local); |
c7108a711 mac80211: Send me... |
446 447 448 |
ifmsh->mesh_cc_id = 0; /* Disabled */ ifmsh->mesh_sp_id = 0; /* Neighbor Offset */ ifmsh->mesh_auth_id = 0; /* Disabled */ |
6b9ac4425 mesh: use set_bit... |
449 |
set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); |
63c5723bc mac80211: add nl8... |
450 |
ieee80211_mesh_root_setup(ifmsh); |
64592c8fc mac80211: use com... |
451 |
ieee80211_queue_work(&local->hw, &sdata->work); |
5b3658342 mac80211: Assign ... |
452 |
sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; |
2d0ddec5b mac80211: unify c... |
453 |
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | |
5b3658342 mac80211: Assign ... |
454 455 |
BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON_INT); |
472dbc45d mac80211: split o... |
456 457 458 459 |
} void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) { |
09b174702 mac80211: move me... |
460 |
struct ieee80211_local *local = sdata->local; |
29cbe68c5 cfg80211/mac80211... |
461 462 463 464 465 |
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; ifmsh->mesh_id_len = 0; ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); sta_info_flush(local, NULL); |
09b174702 mac80211: move me... |
466 |
|
472dbc45d mac80211: split o... |
467 |
del_timer_sync(&sdata->u.mesh.housekeeping_timer); |
e304bfd30 mac80211: impleme... |
468 |
del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); |
472dbc45d mac80211: split o... |
469 |
/* |
b7413430d mac80211: fix wor... |
470 471 472 473 474 475 |
* If the timer fired while we waited for it, it will have * requeued the work. Now the work will be running again * but will not rearm the timer again because it checks * whether the interface is running, which, at this point, * it no longer is. */ |
64592c8fc mac80211: use com... |
476 |
cancel_work_sync(&sdata->work); |
09b174702 mac80211: move me... |
477 478 479 480 |
local->fif_other_bss--; atomic_dec(&local->iff_allmultis); ieee80211_configure_filter(local); |
472dbc45d mac80211: split o... |
481 482 483 484 485 486 487 488 |
} static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, u16 stype, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { |
c6a1fa12d mac80211: minor c... |
489 |
struct ieee80211_local *local = sdata->local; |
472dbc45d mac80211: split o... |
490 491 |
struct ieee802_11_elems elems; struct ieee80211_channel *channel; |
881d948c2 wireless: restric... |
492 |
u32 supp_rates = 0; |
472dbc45d mac80211: split o... |
493 494 495 496 497 498 |
size_t baselen; int freq; enum ieee80211_band band = rx_status->band; /* ignore ProbeResp to foreign address */ if (stype == IEEE80211_STYPE_PROBE_RESP && |
47846c9b0 mac80211: reduce ... |
499 |
compare_ether_addr(mgmt->da, sdata->vif.addr)) |
472dbc45d mac80211: split o... |
500 501 502 503 504 505 506 507 |
return; baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; if (baselen > len) return; ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, &elems); |
5cff5e01e mac80211: ignore ... |
508 |
/* ignore beacons from secure mesh peers if our security is off */ |
b130e5cec nl80211: Introduc... |
509 |
if (elems.rsn_len && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) |
5cff5e01e mac80211: ignore ... |
510 |
return; |
472dbc45d mac80211: split o... |
511 |
if (elems.ds_params && elems.ds_params_len == 1) |
59eb21a65 cfg80211: Extend ... |
512 |
freq = ieee80211_channel_to_frequency(elems.ds_params[0], band); |
472dbc45d mac80211: split o... |
513 514 515 516 517 518 519 520 521 522 523 |
else freq = rx_status->freq; channel = ieee80211_get_channel(local->hw.wiphy, freq); if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) return; if (elems.mesh_id && elems.mesh_config && mesh_matches_local(&elems, sdata)) { supp_rates = ieee80211_sta_get_rates(local, &elems, band); |
1570ca592 mac80211: send no... |
524 |
mesh_neighbour_update(mgmt->sa, supp_rates, sdata, &elems); |
472dbc45d mac80211: split o... |
525 526 527 528 529 530 531 532 533 |
} } static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { switch (mgmt->u.action.category) { |
d3aaec8ab mac80211: Drop ME... |
534 |
case WLAN_CATEGORY_MESH_ACTION: |
472dbc45d mac80211: split o... |
535 536 |
mesh_rx_plink_frame(sdata, mgmt, len, rx_status); break; |
97ad9139f mac80211: Moved m... |
537 |
case WLAN_CATEGORY_MESH_PATH_SEL: |
472dbc45d mac80211: split o... |
538 539 540 541 |
mesh_rx_path_sel_frame(sdata, mgmt, len); break; } } |
1fa57d017 mac80211: use com... |
542 543 |
void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) |
472dbc45d mac80211: split o... |
544 545 |
{ struct ieee80211_rx_status *rx_status; |
472dbc45d mac80211: split o... |
546 547 |
struct ieee80211_mgmt *mgmt; u16 stype; |
f1d58c252 mac80211: push rx... |
548 |
rx_status = IEEE80211_SKB_RXCB(skb); |
472dbc45d mac80211: split o... |
549 550 551 552 553 554 555 556 557 558 559 560 561 |
mgmt = (struct ieee80211_mgmt *) skb->data; stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; switch (stype) { case IEEE80211_STYPE_PROBE_RESP: case IEEE80211_STYPE_BEACON: ieee80211_mesh_rx_bcn_presp(sdata, stype, mgmt, skb->len, rx_status); break; case IEEE80211_STYPE_ACTION: ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status); break; } |
472dbc45d mac80211: split o... |
562 |
} |
1fa57d017 mac80211: use com... |
563 |
void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) |
472dbc45d mac80211: split o... |
564 |
{ |
472dbc45d mac80211: split o... |
565 |
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
472dbc45d mac80211: split o... |
566 567 568 569 570 |
if (ifmsh->preq_queue_len && time_after(jiffies, ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval))) mesh_path_start_discovery(sdata); |
18889231e mac80211: Move mp... |
571 572 |
if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags)) mesh_mpath_table_grow(); |
dcac908ba mac80211:mesh_mpp... |
573 |
if (test_and_clear_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags)) |
18889231e mac80211: Move mp... |
574 575 576 |
mesh_mpp_table_grow(); if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) |
472dbc45d mac80211: split o... |
577 |
ieee80211_mesh_housekeeping(sdata, ifmsh); |
e304bfd30 mac80211: impleme... |
578 579 580 |
if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags)) ieee80211_mesh_rootpath(sdata); |
472dbc45d mac80211: split o... |
581 582 583 584 585 586 587 588 589 |
} void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; rcu_read_lock(); list_for_each_entry_rcu(sdata, &local->interfaces, list) if (ieee80211_vif_is_mesh(&sdata->vif)) |
64592c8fc mac80211: use com... |
590 |
ieee80211_queue_work(&local->hw, &sdata->work); |
472dbc45d mac80211: split o... |
591 592 |
rcu_read_unlock(); } |
902acc789 mac80211: clean u... |
593 594 |
void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) { |
472dbc45d mac80211: split o... |
595 |
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
472dbc45d mac80211: split o... |
596 597 598 |
setup_timer(&ifmsh->housekeeping_timer, ieee80211_mesh_housekeeping_timer, (unsigned long) sdata); |
472dbc45d mac80211: split o... |
599 |
|
472dbc45d mac80211: split o... |
600 601 |
ifmsh->accepting_plinks = true; ifmsh->preq_id = 0; |
d19b3bf63 mac80211: replace... |
602 |
ifmsh->sn = 0; |
472dbc45d mac80211: split o... |
603 |
atomic_set(&ifmsh->mpaths, 0); |
f698d856f replace net_devic... |
604 |
mesh_rmc_init(sdata); |
472dbc45d mac80211: split o... |
605 |
ifmsh->last_preq = jiffies; |
902acc789 mac80211: clean u... |
606 607 608 |
/* Allocate all mesh structures when creating the first mesh interface. */ if (!mesh_allocated) ieee80211s_init(); |
472dbc45d mac80211: split o... |
609 |
setup_timer(&ifmsh->mesh_path_timer, |
902acc789 mac80211: clean u... |
610 611 |
ieee80211_mesh_path_timer, (unsigned long) sdata); |
e304bfd30 mac80211: impleme... |
612 613 614 |
setup_timer(&ifmsh->mesh_path_root_timer, ieee80211_mesh_path_root_timer, (unsigned long) sdata); |
472dbc45d mac80211: split o... |
615 616 617 |
INIT_LIST_HEAD(&ifmsh->preq_queue.list); spin_lock_init(&ifmsh->mesh_preq_queue_lock); } |