~ubuntu-branches/ubuntu/maverick/linux-backports-modules-2.6.32/maverick

« back to all changes in this revision

Viewing changes to updates/compat-wireless-2.6/net/mac80211/mesh_hwmp.c

  • Committer: Bazaar Package Importer
  • Author(s): Andy Whitcroft, Andy Whitcroft
  • Date: 2010-02-04 23:15:51 UTC
  • Revision ID: james.westby@ubuntu.com-20100204231551-vjz5pkvxclukjxm1
Tags: 2.6.32-12.1
[ Andy Whitcroft ]

* initial LBM for lucid
* drop generated files
* printchanges -- rebase tree does not have stable tags use changelog
* printenv -- add revisions to printenv output
* formally rename compat-wireless to linux-backports-modules-wireless
* Update to compat-wireless-2.6.33-rc5
* update nouveau to mainline 2.6.33-rc4
* add new LBM package for nouveau
* nouveau -- fix major numbers and proc entry names
* fix up firmware installs for -wireless
* clean up UPDATE-NOVEAU
* update Nouveau to v2.6.33-rc6

Show diffs side-by-side

added added

removed removed

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