Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/mac80211/mesh_hwmp.c
15109 views
1
/*
2
* Copyright (c) 2008, 2009 open80211s Ltd.
3
* Author: Luis Carlos Cobo <[email protected]>
4
*
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License version 2 as
7
* published by the Free Software Foundation.
8
*/
9
10
#include <linux/slab.h>
11
#include "mesh.h"
12
13
#ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG
14
#define mhwmp_dbg(fmt, args...) printk(KERN_DEBUG "Mesh HWMP: " fmt, ##args)
15
#else
16
#define mhwmp_dbg(fmt, args...) do { (void)(0); } while (0)
17
#endif
18
19
#define TEST_FRAME_LEN 8192
20
#define MAX_METRIC 0xffffffff
21
#define ARITH_SHIFT 8
22
23
/* Number of frames buffered per destination for unresolved destinations */
24
#define MESH_FRAME_QUEUE_LEN 10
25
#define MAX_PREQ_QUEUE_LEN 64
26
27
/* Destination only */
28
#define MP_F_DO 0x1
29
/* Reply and forward */
30
#define MP_F_RF 0x2
31
/* Unknown Sequence Number */
32
#define MP_F_USN 0x01
33
/* Reason code Present */
34
#define MP_F_RCODE 0x02
35
36
static void mesh_queue_preq(struct mesh_path *, u8);
37
38
static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae)
39
{
40
if (ae)
41
offset += 6;
42
return get_unaligned_le32(preq_elem + offset);
43
}
44
45
static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae)
46
{
47
if (ae)
48
offset += 6;
49
return get_unaligned_le16(preq_elem + offset);
50
}
51
52
/* HWMP IE processing macros */
53
#define AE_F (1<<6)
54
#define AE_F_SET(x) (*x & AE_F)
55
#define PREQ_IE_FLAGS(x) (*(x))
56
#define PREQ_IE_HOPCOUNT(x) (*(x + 1))
57
#define PREQ_IE_TTL(x) (*(x + 2))
58
#define PREQ_IE_PREQ_ID(x) u32_field_get(x, 3, 0)
59
#define PREQ_IE_ORIG_ADDR(x) (x + 7)
60
#define PREQ_IE_ORIG_SN(x) u32_field_get(x, 13, 0);
61
#define PREQ_IE_LIFETIME(x) u32_field_get(x, 17, AE_F_SET(x));
62
#define PREQ_IE_METRIC(x) u32_field_get(x, 21, AE_F_SET(x));
63
#define PREQ_IE_TARGET_F(x) (*(AE_F_SET(x) ? x + 32 : x + 26))
64
#define PREQ_IE_TARGET_ADDR(x) (AE_F_SET(x) ? x + 33 : x + 27)
65
#define PREQ_IE_TARGET_SN(x) u32_field_get(x, 33, AE_F_SET(x));
66
67
68
#define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x)
69
#define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x)
70
#define PREP_IE_TTL(x) PREQ_IE_TTL(x)
71
#define PREP_IE_ORIG_ADDR(x) (x + 3)
72
#define PREP_IE_ORIG_SN(x) u32_field_get(x, 9, 0);
73
#define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x));
74
#define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x));
75
#define PREP_IE_TARGET_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21)
76
#define PREP_IE_TARGET_SN(x) u32_field_get(x, 27, AE_F_SET(x));
77
78
#define PERR_IE_TTL(x) (*(x))
79
#define PERR_IE_TARGET_FLAGS(x) (*(x + 2))
80
#define PERR_IE_TARGET_ADDR(x) (x + 3)
81
#define PERR_IE_TARGET_SN(x) u32_field_get(x, 9, 0);
82
#define PERR_IE_TARGET_RCODE(x) u16_field_get(x, 13, 0);
83
84
#define MSEC_TO_TU(x) (x*1000/1024)
85
#define SN_GT(x, y) ((long) (y) - (long) (x) < 0)
86
#define SN_LT(x, y) ((long) (x) - (long) (y) < 0)
87
88
#define net_traversal_jiffies(s) \
89
msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime)
90
#define default_lifetime(s) \
91
MSEC_TO_TU(s->u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout)
92
#define min_preq_int_jiff(s) \
93
(msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval))
94
#define max_preq_retries(s) (s->u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries)
95
#define disc_timeout_jiff(s) \
96
msecs_to_jiffies(sdata->u.mesh.mshcfg.min_discovery_timeout)
97
98
enum mpath_frame_type {
99
MPATH_PREQ = 0,
100
MPATH_PREP,
101
MPATH_PERR,
102
MPATH_RANN
103
};
104
105
static const u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
106
107
static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
108
u8 *orig_addr, __le32 orig_sn, u8 target_flags, u8 *target,
109
__le32 target_sn, const u8 *da, u8 hop_count, u8 ttl,
110
__le32 lifetime, __le32 metric, __le32 preq_id,
111
struct ieee80211_sub_if_data *sdata)
112
{
113
struct ieee80211_local *local = sdata->local;
114
struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
115
struct ieee80211_mgmt *mgmt;
116
u8 *pos;
117
int ie_len;
118
119
if (!skb)
120
return -1;
121
skb_reserve(skb, local->hw.extra_tx_headroom);
122
/* 25 is the size of the common mgmt part (24) plus the size of the
123
* common action part (1)
124
*/
125
mgmt = (struct ieee80211_mgmt *)
126
skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action));
127
memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action));
128
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
129
IEEE80211_STYPE_ACTION);
130
131
memcpy(mgmt->da, da, ETH_ALEN);
132
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
133
/* BSSID == SA */
134
memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
135
mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL;
136
mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION;
137
138
switch (action) {
139
case MPATH_PREQ:
140
mhwmp_dbg("sending PREQ to %pM\n", target);
141
ie_len = 37;
142
pos = skb_put(skb, 2 + ie_len);
143
*pos++ = WLAN_EID_PREQ;
144
break;
145
case MPATH_PREP:
146
mhwmp_dbg("sending PREP to %pM\n", target);
147
ie_len = 31;
148
pos = skb_put(skb, 2 + ie_len);
149
*pos++ = WLAN_EID_PREP;
150
break;
151
case MPATH_RANN:
152
mhwmp_dbg("sending RANN from %pM\n", orig_addr);
153
ie_len = sizeof(struct ieee80211_rann_ie);
154
pos = skb_put(skb, 2 + ie_len);
155
*pos++ = WLAN_EID_RANN;
156
break;
157
default:
158
kfree_skb(skb);
159
return -ENOTSUPP;
160
break;
161
}
162
*pos++ = ie_len;
163
*pos++ = flags;
164
*pos++ = hop_count;
165
*pos++ = ttl;
166
if (action == MPATH_PREQ) {
167
memcpy(pos, &preq_id, 4);
168
pos += 4;
169
}
170
memcpy(pos, orig_addr, ETH_ALEN);
171
pos += ETH_ALEN;
172
memcpy(pos, &orig_sn, 4);
173
pos += 4;
174
if (action != MPATH_RANN) {
175
memcpy(pos, &lifetime, 4);
176
pos += 4;
177
}
178
memcpy(pos, &metric, 4);
179
pos += 4;
180
if (action == MPATH_PREQ) {
181
/* destination count */
182
*pos++ = 1;
183
*pos++ = target_flags;
184
}
185
if (action != MPATH_RANN) {
186
memcpy(pos, target, ETH_ALEN);
187
pos += ETH_ALEN;
188
memcpy(pos, &target_sn, 4);
189
}
190
191
ieee80211_tx_skb(sdata, skb);
192
return 0;
193
}
194
195
/**
196
* mesh_send_path error - Sends a PERR mesh management frame
197
*
198
* @target: broken destination
199
* @target_sn: SN of the broken destination
200
* @target_rcode: reason code for this PERR
201
* @ra: node this frame is addressed to
202
*/
203
int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
204
__le16 target_rcode, const u8 *ra,
205
struct ieee80211_sub_if_data *sdata)
206
{
207
struct ieee80211_local *local = sdata->local;
208
struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
209
struct ieee80211_mgmt *mgmt;
210
u8 *pos;
211
int ie_len;
212
213
if (!skb)
214
return -1;
215
skb_reserve(skb, local->hw.extra_tx_headroom);
216
/* 25 is the size of the common mgmt part (24) plus the size of the
217
* common action part (1)
218
*/
219
mgmt = (struct ieee80211_mgmt *)
220
skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action));
221
memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action));
222
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
223
IEEE80211_STYPE_ACTION);
224
225
memcpy(mgmt->da, ra, ETH_ALEN);
226
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
227
/* BSSID is left zeroed, wildcard value */
228
mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL;
229
mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION;
230
ie_len = 15;
231
pos = skb_put(skb, 2 + ie_len);
232
*pos++ = WLAN_EID_PERR;
233
*pos++ = ie_len;
234
/* ttl */
235
*pos++ = ttl;
236
/* number of destinations */
237
*pos++ = 1;
238
/*
239
* flags bit, bit 1 is unset if we know the sequence number and
240
* bit 2 is set if we have a reason code
241
*/
242
*pos = 0;
243
if (!target_sn)
244
*pos |= MP_F_USN;
245
if (target_rcode)
246
*pos |= MP_F_RCODE;
247
pos++;
248
memcpy(pos, target, ETH_ALEN);
249
pos += ETH_ALEN;
250
memcpy(pos, &target_sn, 4);
251
pos += 4;
252
memcpy(pos, &target_rcode, 2);
253
254
ieee80211_tx_skb(sdata, skb);
255
return 0;
256
}
257
258
void ieee80211s_update_metric(struct ieee80211_local *local,
259
struct sta_info *stainfo, struct sk_buff *skb)
260
{
261
struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
262
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
263
int failed;
264
265
if (!ieee80211_is_data(hdr->frame_control))
266
return;
267
268
failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);
269
270
/* moving average, scaled to 100 */
271
stainfo->fail_avg = ((80 * stainfo->fail_avg + 5) / 100 + 20 * failed);
272
if (stainfo->fail_avg > 95)
273
mesh_plink_broken(stainfo);
274
}
275
276
static u32 airtime_link_metric_get(struct ieee80211_local *local,
277
struct sta_info *sta)
278
{
279
struct ieee80211_supported_band *sband;
280
/* This should be adjusted for each device */
281
int device_constant = 1 << ARITH_SHIFT;
282
int test_frame_len = TEST_FRAME_LEN << ARITH_SHIFT;
283
int s_unit = 1 << ARITH_SHIFT;
284
int rate, err;
285
u32 tx_time, estimated_retx;
286
u64 result;
287
288
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
289
290
if (sta->fail_avg >= 100)
291
return MAX_METRIC;
292
293
if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
294
return MAX_METRIC;
295
296
err = (sta->fail_avg << ARITH_SHIFT) / 100;
297
298
/* bitrate is in units of 100 Kbps, while we need rate in units of
299
* 1Mbps. This will be corrected on tx_time computation.
300
*/
301
rate = sband->bitrates[sta->last_tx_rate.idx].bitrate;
302
tx_time = (device_constant + 10 * test_frame_len / rate);
303
estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err));
304
result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ;
305
return (u32)result;
306
}
307
308
/**
309
* hwmp_route_info_get - Update routing info to originator and transmitter
310
*
311
* @sdata: local mesh subif
312
* @mgmt: mesh management frame
313
* @hwmp_ie: hwmp information element (PREP or PREQ)
314
*
315
* This function updates the path routing information to the originator and the
316
* transmitter of a HWMP PREQ or PREP frame.
317
*
318
* Returns: metric to frame originator or 0 if the frame should not be further
319
* processed
320
*
321
* Notes: this function is the only place (besides user-provided info) where
322
* path routing information is updated.
323
*/
324
static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
325
struct ieee80211_mgmt *mgmt,
326
u8 *hwmp_ie, enum mpath_frame_type action)
327
{
328
struct ieee80211_local *local = sdata->local;
329
struct mesh_path *mpath;
330
struct sta_info *sta;
331
bool fresh_info;
332
u8 *orig_addr, *ta;
333
u32 orig_sn, orig_metric;
334
unsigned long orig_lifetime, exp_time;
335
u32 last_hop_metric, new_metric;
336
bool process = true;
337
338
rcu_read_lock();
339
sta = sta_info_get(sdata, mgmt->sa);
340
if (!sta) {
341
rcu_read_unlock();
342
return 0;
343
}
344
345
last_hop_metric = airtime_link_metric_get(local, sta);
346
/* Update and check originator routing info */
347
fresh_info = true;
348
349
switch (action) {
350
case MPATH_PREQ:
351
orig_addr = PREQ_IE_ORIG_ADDR(hwmp_ie);
352
orig_sn = PREQ_IE_ORIG_SN(hwmp_ie);
353
orig_lifetime = PREQ_IE_LIFETIME(hwmp_ie);
354
orig_metric = PREQ_IE_METRIC(hwmp_ie);
355
break;
356
case MPATH_PREP:
357
/* Originator here refers to the MP that was the destination in
358
* the Path Request. The draft refers to that MP as the
359
* destination address, even though usually it is the origin of
360
* the PREP frame. We divert from the nomenclature in the draft
361
* so that we can easily use a single function to gather path
362
* information from both PREQ and PREP frames.
363
*/
364
orig_addr = PREP_IE_ORIG_ADDR(hwmp_ie);
365
orig_sn = PREP_IE_ORIG_SN(hwmp_ie);
366
orig_lifetime = PREP_IE_LIFETIME(hwmp_ie);
367
orig_metric = PREP_IE_METRIC(hwmp_ie);
368
break;
369
default:
370
rcu_read_unlock();
371
return 0;
372
}
373
new_metric = orig_metric + last_hop_metric;
374
if (new_metric < orig_metric)
375
new_metric = MAX_METRIC;
376
exp_time = TU_TO_EXP_TIME(orig_lifetime);
377
378
if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0) {
379
/* This MP is the originator, we are not interested in this
380
* frame, except for updating transmitter's path info.
381
*/
382
process = false;
383
fresh_info = false;
384
} else {
385
mpath = mesh_path_lookup(orig_addr, sdata);
386
if (mpath) {
387
spin_lock_bh(&mpath->state_lock);
388
if (mpath->flags & MESH_PATH_FIXED)
389
fresh_info = false;
390
else if ((mpath->flags & MESH_PATH_ACTIVE) &&
391
(mpath->flags & MESH_PATH_SN_VALID)) {
392
if (SN_GT(mpath->sn, orig_sn) ||
393
(mpath->sn == orig_sn &&
394
new_metric >= mpath->metric)) {
395
process = false;
396
fresh_info = false;
397
}
398
}
399
} else {
400
mesh_path_add(orig_addr, sdata);
401
mpath = mesh_path_lookup(orig_addr, sdata);
402
if (!mpath) {
403
rcu_read_unlock();
404
return 0;
405
}
406
spin_lock_bh(&mpath->state_lock);
407
}
408
409
if (fresh_info) {
410
mesh_path_assign_nexthop(mpath, sta);
411
mpath->flags |= MESH_PATH_SN_VALID;
412
mpath->metric = new_metric;
413
mpath->sn = orig_sn;
414
mpath->exp_time = time_after(mpath->exp_time, exp_time)
415
? mpath->exp_time : exp_time;
416
mesh_path_activate(mpath);
417
spin_unlock_bh(&mpath->state_lock);
418
mesh_path_tx_pending(mpath);
419
/* draft says preq_id should be saved to, but there does
420
* not seem to be any use for it, skipping by now
421
*/
422
} else
423
spin_unlock_bh(&mpath->state_lock);
424
}
425
426
/* Update and check transmitter routing info */
427
ta = mgmt->sa;
428
if (memcmp(orig_addr, ta, ETH_ALEN) == 0)
429
fresh_info = false;
430
else {
431
fresh_info = true;
432
433
mpath = mesh_path_lookup(ta, sdata);
434
if (mpath) {
435
spin_lock_bh(&mpath->state_lock);
436
if ((mpath->flags & MESH_PATH_FIXED) ||
437
((mpath->flags & MESH_PATH_ACTIVE) &&
438
(last_hop_metric > mpath->metric)))
439
fresh_info = false;
440
} else {
441
mesh_path_add(ta, sdata);
442
mpath = mesh_path_lookup(ta, sdata);
443
if (!mpath) {
444
rcu_read_unlock();
445
return 0;
446
}
447
spin_lock_bh(&mpath->state_lock);
448
}
449
450
if (fresh_info) {
451
mesh_path_assign_nexthop(mpath, sta);
452
mpath->flags &= ~MESH_PATH_SN_VALID;
453
mpath->metric = last_hop_metric;
454
mpath->exp_time = time_after(mpath->exp_time, exp_time)
455
? mpath->exp_time : exp_time;
456
mesh_path_activate(mpath);
457
spin_unlock_bh(&mpath->state_lock);
458
mesh_path_tx_pending(mpath);
459
} else
460
spin_unlock_bh(&mpath->state_lock);
461
}
462
463
rcu_read_unlock();
464
465
return process ? new_metric : 0;
466
}
467
468
static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
469
struct ieee80211_mgmt *mgmt,
470
u8 *preq_elem, u32 metric)
471
{
472
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
473
struct mesh_path *mpath;
474
u8 *target_addr, *orig_addr;
475
u8 target_flags, ttl;
476
u32 orig_sn, target_sn, lifetime;
477
bool reply = false;
478
bool forward = true;
479
480
/* Update target SN, if present */
481
target_addr = PREQ_IE_TARGET_ADDR(preq_elem);
482
orig_addr = PREQ_IE_ORIG_ADDR(preq_elem);
483
target_sn = PREQ_IE_TARGET_SN(preq_elem);
484
orig_sn = PREQ_IE_ORIG_SN(preq_elem);
485
target_flags = PREQ_IE_TARGET_F(preq_elem);
486
487
mhwmp_dbg("received PREQ from %pM\n", orig_addr);
488
489
if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) {
490
mhwmp_dbg("PREQ is for us\n");
491
forward = false;
492
reply = true;
493
metric = 0;
494
if (time_after(jiffies, ifmsh->last_sn_update +
495
net_traversal_jiffies(sdata)) ||
496
time_before(jiffies, ifmsh->last_sn_update)) {
497
target_sn = ++ifmsh->sn;
498
ifmsh->last_sn_update = jiffies;
499
}
500
} else {
501
rcu_read_lock();
502
mpath = mesh_path_lookup(target_addr, sdata);
503
if (mpath) {
504
if ((!(mpath->flags & MESH_PATH_SN_VALID)) ||
505
SN_LT(mpath->sn, target_sn)) {
506
mpath->sn = target_sn;
507
mpath->flags |= MESH_PATH_SN_VALID;
508
} else if ((!(target_flags & MP_F_DO)) &&
509
(mpath->flags & MESH_PATH_ACTIVE)) {
510
reply = true;
511
metric = mpath->metric;
512
target_sn = mpath->sn;
513
if (target_flags & MP_F_RF)
514
target_flags |= MP_F_DO;
515
else
516
forward = false;
517
}
518
}
519
rcu_read_unlock();
520
}
521
522
if (reply) {
523
lifetime = PREQ_IE_LIFETIME(preq_elem);
524
ttl = ifmsh->mshcfg.element_ttl;
525
if (ttl != 0) {
526
mhwmp_dbg("replying to the PREQ\n");
527
mesh_path_sel_frame_tx(MPATH_PREP, 0, target_addr,
528
cpu_to_le32(target_sn), 0, orig_addr,
529
cpu_to_le32(orig_sn), mgmt->sa, 0, ttl,
530
cpu_to_le32(lifetime), cpu_to_le32(metric),
531
0, sdata);
532
} else
533
ifmsh->mshstats.dropped_frames_ttl++;
534
}
535
536
if (forward) {
537
u32 preq_id;
538
u8 hopcount, flags;
539
540
ttl = PREQ_IE_TTL(preq_elem);
541
lifetime = PREQ_IE_LIFETIME(preq_elem);
542
if (ttl <= 1) {
543
ifmsh->mshstats.dropped_frames_ttl++;
544
return;
545
}
546
mhwmp_dbg("forwarding the PREQ from %pM\n", orig_addr);
547
--ttl;
548
flags = PREQ_IE_FLAGS(preq_elem);
549
preq_id = PREQ_IE_PREQ_ID(preq_elem);
550
hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1;
551
mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr,
552
cpu_to_le32(orig_sn), target_flags, target_addr,
553
cpu_to_le32(target_sn), broadcast_addr,
554
hopcount, ttl, cpu_to_le32(lifetime),
555
cpu_to_le32(metric), cpu_to_le32(preq_id),
556
sdata);
557
ifmsh->mshstats.fwded_mcast++;
558
ifmsh->mshstats.fwded_frames++;
559
}
560
}
561
562
563
static inline struct sta_info *
564
next_hop_deref_protected(struct mesh_path *mpath)
565
{
566
return rcu_dereference_protected(mpath->next_hop,
567
lockdep_is_held(&mpath->state_lock));
568
}
569
570
571
static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
572
struct ieee80211_mgmt *mgmt,
573
u8 *prep_elem, u32 metric)
574
{
575
struct mesh_path *mpath;
576
u8 *target_addr, *orig_addr;
577
u8 ttl, hopcount, flags;
578
u8 next_hop[ETH_ALEN];
579
u32 target_sn, orig_sn, lifetime;
580
581
mhwmp_dbg("received PREP from %pM\n", PREP_IE_ORIG_ADDR(prep_elem));
582
583
/* Note that we divert from the draft nomenclature and denominate
584
* destination to what the draft refers to as origininator. So in this
585
* function destnation refers to the final destination of the PREP,
586
* which corresponds with the originator of the PREQ which this PREP
587
* replies
588
*/
589
target_addr = PREP_IE_TARGET_ADDR(prep_elem);
590
if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0)
591
/* destination, no forwarding required */
592
return;
593
594
ttl = PREP_IE_TTL(prep_elem);
595
if (ttl <= 1) {
596
sdata->u.mesh.mshstats.dropped_frames_ttl++;
597
return;
598
}
599
600
rcu_read_lock();
601
mpath = mesh_path_lookup(target_addr, sdata);
602
if (mpath)
603
spin_lock_bh(&mpath->state_lock);
604
else
605
goto fail;
606
if (!(mpath->flags & MESH_PATH_ACTIVE)) {
607
spin_unlock_bh(&mpath->state_lock);
608
goto fail;
609
}
610
memcpy(next_hop, next_hop_deref_protected(mpath)->sta.addr, ETH_ALEN);
611
spin_unlock_bh(&mpath->state_lock);
612
--ttl;
613
flags = PREP_IE_FLAGS(prep_elem);
614
lifetime = PREP_IE_LIFETIME(prep_elem);
615
hopcount = PREP_IE_HOPCOUNT(prep_elem) + 1;
616
orig_addr = PREP_IE_ORIG_ADDR(prep_elem);
617
target_sn = PREP_IE_TARGET_SN(prep_elem);
618
orig_sn = PREP_IE_ORIG_SN(prep_elem);
619
620
mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr,
621
cpu_to_le32(orig_sn), 0, target_addr,
622
cpu_to_le32(target_sn), next_hop, hopcount,
623
ttl, cpu_to_le32(lifetime), cpu_to_le32(metric),
624
0, sdata);
625
rcu_read_unlock();
626
627
sdata->u.mesh.mshstats.fwded_unicast++;
628
sdata->u.mesh.mshstats.fwded_frames++;
629
return;
630
631
fail:
632
rcu_read_unlock();
633
sdata->u.mesh.mshstats.dropped_frames_no_route++;
634
}
635
636
static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
637
struct ieee80211_mgmt *mgmt, u8 *perr_elem)
638
{
639
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
640
struct mesh_path *mpath;
641
u8 ttl;
642
u8 *ta, *target_addr;
643
u32 target_sn;
644
u16 target_rcode;
645
646
ta = mgmt->sa;
647
ttl = PERR_IE_TTL(perr_elem);
648
if (ttl <= 1) {
649
ifmsh->mshstats.dropped_frames_ttl++;
650
return;
651
}
652
ttl--;
653
target_addr = PERR_IE_TARGET_ADDR(perr_elem);
654
target_sn = PERR_IE_TARGET_SN(perr_elem);
655
target_rcode = PERR_IE_TARGET_RCODE(perr_elem);
656
657
rcu_read_lock();
658
mpath = mesh_path_lookup(target_addr, sdata);
659
if (mpath) {
660
spin_lock_bh(&mpath->state_lock);
661
if (mpath->flags & MESH_PATH_ACTIVE &&
662
memcmp(ta, next_hop_deref_protected(mpath)->sta.addr,
663
ETH_ALEN) == 0 &&
664
(!(mpath->flags & MESH_PATH_SN_VALID) ||
665
SN_GT(target_sn, mpath->sn))) {
666
mpath->flags &= ~MESH_PATH_ACTIVE;
667
mpath->sn = target_sn;
668
spin_unlock_bh(&mpath->state_lock);
669
mesh_path_error_tx(ttl, target_addr, cpu_to_le32(target_sn),
670
cpu_to_le16(target_rcode),
671
broadcast_addr, sdata);
672
} else
673
spin_unlock_bh(&mpath->state_lock);
674
}
675
rcu_read_unlock();
676
}
677
678
static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
679
struct ieee80211_mgmt *mgmt,
680
struct ieee80211_rann_ie *rann)
681
{
682
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
683
struct mesh_path *mpath;
684
u8 ttl, flags, hopcount;
685
u8 *orig_addr;
686
u32 orig_sn, metric;
687
688
ttl = rann->rann_ttl;
689
if (ttl <= 1) {
690
ifmsh->mshstats.dropped_frames_ttl++;
691
return;
692
}
693
ttl--;
694
flags = rann->rann_flags;
695
orig_addr = rann->rann_addr;
696
orig_sn = rann->rann_seq;
697
hopcount = rann->rann_hopcount;
698
hopcount++;
699
metric = rann->rann_metric;
700
mhwmp_dbg("received RANN from %pM\n", orig_addr);
701
702
rcu_read_lock();
703
mpath = mesh_path_lookup(orig_addr, sdata);
704
if (!mpath) {
705
mesh_path_add(orig_addr, sdata);
706
mpath = mesh_path_lookup(orig_addr, sdata);
707
if (!mpath) {
708
rcu_read_unlock();
709
sdata->u.mesh.mshstats.dropped_frames_no_route++;
710
return;
711
}
712
mesh_queue_preq(mpath,
713
PREQ_Q_F_START | PREQ_Q_F_REFRESH);
714
}
715
if (mpath->sn < orig_sn) {
716
mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
717
cpu_to_le32(orig_sn),
718
0, NULL, 0, broadcast_addr,
719
hopcount, ttl, 0,
720
cpu_to_le32(metric + mpath->metric),
721
0, sdata);
722
mpath->sn = orig_sn;
723
}
724
rcu_read_unlock();
725
}
726
727
728
void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
729
struct ieee80211_mgmt *mgmt,
730
size_t len)
731
{
732
struct ieee802_11_elems elems;
733
size_t baselen;
734
u32 last_hop_metric;
735
736
/* need action_code */
737
if (len < IEEE80211_MIN_ACTION_SIZE + 1)
738
return;
739
740
baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
741
ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
742
len - baselen, &elems);
743
744
if (elems.preq) {
745
if (elems.preq_len != 37)
746
/* Right now we support just 1 destination and no AE */
747
return;
748
last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.preq,
749
MPATH_PREQ);
750
if (last_hop_metric)
751
hwmp_preq_frame_process(sdata, mgmt, elems.preq,
752
last_hop_metric);
753
}
754
if (elems.prep) {
755
if (elems.prep_len != 31)
756
/* Right now we support no AE */
757
return;
758
last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.prep,
759
MPATH_PREP);
760
if (last_hop_metric)
761
hwmp_prep_frame_process(sdata, mgmt, elems.prep,
762
last_hop_metric);
763
}
764
if (elems.perr) {
765
if (elems.perr_len != 15)
766
/* Right now we support only one destination per PERR */
767
return;
768
hwmp_perr_frame_process(sdata, mgmt, elems.perr);
769
}
770
if (elems.rann)
771
hwmp_rann_frame_process(sdata, mgmt, elems.rann);
772
}
773
774
/**
775
* mesh_queue_preq - queue a PREQ to a given destination
776
*
777
* @mpath: mesh path to discover
778
* @flags: special attributes of the PREQ to be sent
779
*
780
* Locking: the function must be called from within a rcu read lock block.
781
*
782
*/
783
static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
784
{
785
struct ieee80211_sub_if_data *sdata = mpath->sdata;
786
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
787
struct mesh_preq_queue *preq_node;
788
789
preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC);
790
if (!preq_node) {
791
mhwmp_dbg("could not allocate PREQ node\n");
792
return;
793
}
794
795
spin_lock(&ifmsh->mesh_preq_queue_lock);
796
if (ifmsh->preq_queue_len == MAX_PREQ_QUEUE_LEN) {
797
spin_unlock(&ifmsh->mesh_preq_queue_lock);
798
kfree(preq_node);
799
if (printk_ratelimit())
800
mhwmp_dbg("PREQ node queue full\n");
801
return;
802
}
803
804
memcpy(preq_node->dst, mpath->dst, ETH_ALEN);
805
preq_node->flags = flags;
806
807
list_add_tail(&preq_node->list, &ifmsh->preq_queue.list);
808
++ifmsh->preq_queue_len;
809
spin_unlock(&ifmsh->mesh_preq_queue_lock);
810
811
if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata)))
812
ieee80211_queue_work(&sdata->local->hw, &sdata->work);
813
814
else if (time_before(jiffies, ifmsh->last_preq)) {
815
/* avoid long wait if did not send preqs for a long time
816
* and jiffies wrapped around
817
*/
818
ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
819
ieee80211_queue_work(&sdata->local->hw, &sdata->work);
820
} else
821
mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq +
822
min_preq_int_jiff(sdata));
823
}
824
825
/**
826
* mesh_path_start_discovery - launch a path discovery from the PREQ queue
827
*
828
* @sdata: local mesh subif
829
*/
830
void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
831
{
832
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
833
struct mesh_preq_queue *preq_node;
834
struct mesh_path *mpath;
835
u8 ttl, target_flags;
836
u32 lifetime;
837
838
spin_lock_bh(&ifmsh->mesh_preq_queue_lock);
839
if (!ifmsh->preq_queue_len ||
840
time_before(jiffies, ifmsh->last_preq +
841
min_preq_int_jiff(sdata))) {
842
spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
843
return;
844
}
845
846
preq_node = list_first_entry(&ifmsh->preq_queue.list,
847
struct mesh_preq_queue, list);
848
list_del(&preq_node->list);
849
--ifmsh->preq_queue_len;
850
spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
851
852
rcu_read_lock();
853
mpath = mesh_path_lookup(preq_node->dst, sdata);
854
if (!mpath)
855
goto enddiscovery;
856
857
spin_lock_bh(&mpath->state_lock);
858
if (preq_node->flags & PREQ_Q_F_START) {
859
if (mpath->flags & MESH_PATH_RESOLVING) {
860
spin_unlock_bh(&mpath->state_lock);
861
goto enddiscovery;
862
} else {
863
mpath->flags &= ~MESH_PATH_RESOLVED;
864
mpath->flags |= MESH_PATH_RESOLVING;
865
mpath->discovery_retries = 0;
866
mpath->discovery_timeout = disc_timeout_jiff(sdata);
867
}
868
} else if (!(mpath->flags & MESH_PATH_RESOLVING) ||
869
mpath->flags & MESH_PATH_RESOLVED) {
870
mpath->flags &= ~MESH_PATH_RESOLVING;
871
spin_unlock_bh(&mpath->state_lock);
872
goto enddiscovery;
873
}
874
875
ifmsh->last_preq = jiffies;
876
877
if (time_after(jiffies, ifmsh->last_sn_update +
878
net_traversal_jiffies(sdata)) ||
879
time_before(jiffies, ifmsh->last_sn_update)) {
880
++ifmsh->sn;
881
sdata->u.mesh.last_sn_update = jiffies;
882
}
883
lifetime = default_lifetime(sdata);
884
ttl = sdata->u.mesh.mshcfg.element_ttl;
885
if (ttl == 0) {
886
sdata->u.mesh.mshstats.dropped_frames_ttl++;
887
spin_unlock_bh(&mpath->state_lock);
888
goto enddiscovery;
889
}
890
891
if (preq_node->flags & PREQ_Q_F_REFRESH)
892
target_flags = MP_F_DO;
893
else
894
target_flags = MP_F_RF;
895
896
spin_unlock_bh(&mpath->state_lock);
897
mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr,
898
cpu_to_le32(ifmsh->sn), target_flags, mpath->dst,
899
cpu_to_le32(mpath->sn), broadcast_addr, 0,
900
ttl, cpu_to_le32(lifetime), 0,
901
cpu_to_le32(ifmsh->preq_id++), sdata);
902
mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
903
904
enddiscovery:
905
rcu_read_unlock();
906
kfree(preq_node);
907
}
908
909
/**
910
* mesh_nexthop_lookup - put the appropriate next hop on a mesh frame
911
*
912
* @skb: 802.11 frame to be sent
913
* @sdata: network subif the frame will be sent through
914
*
915
* Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is
916
* found, the function will start a path discovery and queue the frame so it is
917
* sent when the path is resolved. This means the caller must not free the skb
918
* in this case.
919
*/
920
int mesh_nexthop_lookup(struct sk_buff *skb,
921
struct ieee80211_sub_if_data *sdata)
922
{
923
struct sk_buff *skb_to_free = NULL;
924
struct mesh_path *mpath;
925
struct sta_info *next_hop;
926
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
927
u8 *target_addr = hdr->addr3;
928
int err = 0;
929
930
rcu_read_lock();
931
mpath = mesh_path_lookup(target_addr, sdata);
932
933
if (!mpath) {
934
mesh_path_add(target_addr, sdata);
935
mpath = mesh_path_lookup(target_addr, sdata);
936
if (!mpath) {
937
sdata->u.mesh.mshstats.dropped_frames_no_route++;
938
err = -ENOSPC;
939
goto endlookup;
940
}
941
}
942
943
if (mpath->flags & MESH_PATH_ACTIVE) {
944
if (time_after(jiffies,
945
mpath->exp_time -
946
msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) &&
947
!memcmp(sdata->vif.addr, hdr->addr4, ETH_ALEN) &&
948
!(mpath->flags & MESH_PATH_RESOLVING) &&
949
!(mpath->flags & MESH_PATH_FIXED)) {
950
mesh_queue_preq(mpath,
951
PREQ_Q_F_START | PREQ_Q_F_REFRESH);
952
}
953
next_hop = rcu_dereference(mpath->next_hop);
954
if (next_hop)
955
memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN);
956
else
957
err = -ENOENT;
958
} else {
959
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
960
if (!(mpath->flags & MESH_PATH_RESOLVING)) {
961
/* Start discovery only if it is not running yet */
962
mesh_queue_preq(mpath, PREQ_Q_F_START);
963
}
964
965
if (skb_queue_len(&mpath->frame_queue) >=
966
MESH_FRAME_QUEUE_LEN)
967
skb_to_free = skb_dequeue(&mpath->frame_queue);
968
969
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
970
skb_queue_tail(&mpath->frame_queue, skb);
971
if (skb_to_free)
972
mesh_path_discard_frame(skb_to_free, sdata);
973
err = -ENOENT;
974
}
975
976
endlookup:
977
rcu_read_unlock();
978
return err;
979
}
980
981
void mesh_path_timer(unsigned long data)
982
{
983
struct mesh_path *mpath = (void *) data;
984
struct ieee80211_sub_if_data *sdata = mpath->sdata;
985
986
if (sdata->local->quiescing)
987
return;
988
989
spin_lock_bh(&mpath->state_lock);
990
if (mpath->flags & MESH_PATH_RESOLVED ||
991
(!(mpath->flags & MESH_PATH_RESOLVING)))
992
mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED);
993
else if (mpath->discovery_retries < max_preq_retries(sdata)) {
994
++mpath->discovery_retries;
995
mpath->discovery_timeout *= 2;
996
mesh_queue_preq(mpath, 0);
997
} else {
998
mpath->flags = 0;
999
mpath->exp_time = jiffies;
1000
mesh_path_flush_pending(mpath);
1001
}
1002
1003
spin_unlock_bh(&mpath->state_lock);
1004
}
1005
1006
void
1007
mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
1008
{
1009
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
1010
1011
mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr,
1012
cpu_to_le32(++ifmsh->sn),
1013
0, NULL, 0, broadcast_addr,
1014
0, sdata->u.mesh.mshcfg.element_ttl,
1015
0, 0, 0, sdata);
1016
}
1017
1018