Deleted Added
full compact
ieee80211_mesh.c (195661) ieee80211_mesh.c (195784)
1/*-
2 * Copyright (c) 2009 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Rui Paulo under sponsorship from the
6 * FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 14 unchanged lines hidden (view full) ---

23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29#include <sys/cdefs.h>
30#ifdef __FreeBSD__
1/*-
2 * Copyright (c) 2009 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Rui Paulo under sponsorship from the
6 * FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 14 unchanged lines hidden (view full) ---

23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29#include <sys/cdefs.h>
30#ifdef __FreeBSD__
31__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_mesh.c 195661 2009-07-13 18:23:58Z rpaulo $");
31__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_mesh.c 195784 2009-07-20 19:12:08Z rpaulo $");
32#endif
33
34/*
35 * IEEE 802.11s Mesh Point (MBSS) support.
36 *
37 * Based on March 2009, D3.0 802.11s draft spec.
38 */
39#include "opt_inet.h"

--- 17 unchanged lines hidden (view full) ---

57#include <net/if_llc.h>
58#include <net/ethernet.h>
59
60#include <net80211/ieee80211_var.h>
61#include <net80211/ieee80211_action.h>
62#include <net80211/ieee80211_input.h>
63#include <net80211/ieee80211_mesh.h>
64
32#endif
33
34/*
35 * IEEE 802.11s Mesh Point (MBSS) support.
36 *
37 * Based on March 2009, D3.0 802.11s draft spec.
38 */
39#include "opt_inet.h"

--- 17 unchanged lines hidden (view full) ---

57#include <net/if_llc.h>
58#include <net/ethernet.h>
59
60#include <net80211/ieee80211_var.h>
61#include <net80211/ieee80211_action.h>
62#include <net80211/ieee80211_input.h>
63#include <net80211/ieee80211_mesh.h>
64
65static void mesh_rt_flush_invalid(struct ieee80211vap *);
65static int mesh_select_proto_path(struct ieee80211vap *, const char *);
66static int mesh_select_proto_metric(struct ieee80211vap *, const char *);
67static void mesh_vattach(struct ieee80211vap *);
68static int mesh_newstate(struct ieee80211vap *, enum ieee80211_state, int);
66static int mesh_select_proto_path(struct ieee80211vap *, const char *);
67static int mesh_select_proto_metric(struct ieee80211vap *, const char *);
68static void mesh_vattach(struct ieee80211vap *);
69static int mesh_newstate(struct ieee80211vap *, enum ieee80211_state, int);
70static void mesh_rt_cleanup_cb(void *);
69static void mesh_linkchange(struct ieee80211_node *,
70 enum ieee80211_mesh_mlstate);
71static void mesh_checkid(void *, struct ieee80211_node *);
72static uint32_t mesh_generateid(struct ieee80211vap *);
73static int mesh_checkpseq(struct ieee80211vap *,
74 const uint8_t [IEEE80211_ADDR_LEN], uint32_t);
75static struct ieee80211_node *
76 mesh_find_txnode(struct ieee80211vap *,

--- 56 unchanged lines hidden (view full) ---

133 .mpm_ie = IEEE80211_MESHCONF_AIRTIME,
134 .mpm_metric = mesh_airtime_calc,
135};
136
137static struct ieee80211_mesh_proto_path mesh_proto_paths[4];
138static struct ieee80211_mesh_proto_metric mesh_proto_metrics[4];
139
140#define MESH_RT_LOCK(ms) mtx_lock(&(ms)->ms_rt_lock)
71static void mesh_linkchange(struct ieee80211_node *,
72 enum ieee80211_mesh_mlstate);
73static void mesh_checkid(void *, struct ieee80211_node *);
74static uint32_t mesh_generateid(struct ieee80211vap *);
75static int mesh_checkpseq(struct ieee80211vap *,
76 const uint8_t [IEEE80211_ADDR_LEN], uint32_t);
77static struct ieee80211_node *
78 mesh_find_txnode(struct ieee80211vap *,

--- 56 unchanged lines hidden (view full) ---

135 .mpm_ie = IEEE80211_MESHCONF_AIRTIME,
136 .mpm_metric = mesh_airtime_calc,
137};
138
139static struct ieee80211_mesh_proto_path mesh_proto_paths[4];
140static struct ieee80211_mesh_proto_metric mesh_proto_metrics[4];
141
142#define MESH_RT_LOCK(ms) mtx_lock(&(ms)->ms_rt_lock)
143#define MESH_RT_LOCK_ASSERT(ms) mtx_assert(&(ms)->ms_rt_lock, MA_OWNED)
141#define MESH_RT_UNLOCK(ms) mtx_unlock(&(ms)->ms_rt_lock)
142
143MALLOC_DEFINE(M_80211_MESH_RT, "80211mesh", "802.11s routing table");
144
145/*
146 * Helper functions to manipulate the Mesh routing table.
147 */
144#define MESH_RT_UNLOCK(ms) mtx_unlock(&(ms)->ms_rt_lock)
145
146MALLOC_DEFINE(M_80211_MESH_RT, "80211mesh", "802.11s routing table");
147
148/*
149 * Helper functions to manipulate the Mesh routing table.
150 */
151
152static struct ieee80211_mesh_route *
153mesh_rt_find_locked(struct ieee80211_mesh_state *ms,
154 const uint8_t dest[IEEE80211_ADDR_LEN])
155{
156 struct ieee80211_mesh_route *rt;
157
158 MESH_RT_LOCK_ASSERT(ms);
159
160 TAILQ_FOREACH(rt, &ms->ms_routes, rt_next) {
161 if (IEEE80211_ADDR_EQ(dest, rt->rt_dest))
162 return rt;
163 }
164 return NULL;
165}
166
167static struct ieee80211_mesh_route *
168mesh_rt_add_locked(struct ieee80211_mesh_state *ms,
169 const uint8_t dest[IEEE80211_ADDR_LEN])
170{
171 struct ieee80211_mesh_route *rt;
172
173 KASSERT(!IEEE80211_ADDR_EQ(broadcastaddr, dest),
174 ("%s: adding broadcast to the routing table", __func__));
175
176 MESH_RT_LOCK_ASSERT(ms);
177
178 rt = malloc(ALIGN(sizeof(struct ieee80211_mesh_route)) +
179 ms->ms_ppath->mpp_privlen, M_80211_MESH_RT, M_NOWAIT | M_ZERO);
180 if (rt != NULL) {
181 IEEE80211_ADDR_COPY(rt->rt_dest, dest);
182 rt->rt_priv = (void *)ALIGN(&rt[1]);
183 getmicrouptime(&rt->rt_crtime);
184 TAILQ_INSERT_TAIL(&ms->ms_routes, rt, rt_next);
185 }
186 return rt;
187}
188
148struct ieee80211_mesh_route *
149ieee80211_mesh_rt_find(struct ieee80211vap *vap,
150 const uint8_t dest[IEEE80211_ADDR_LEN])
151{
152 struct ieee80211_mesh_state *ms = vap->iv_mesh;
153 struct ieee80211_mesh_route *rt;
154
155 MESH_RT_LOCK(ms);
189struct ieee80211_mesh_route *
190ieee80211_mesh_rt_find(struct ieee80211vap *vap,
191 const uint8_t dest[IEEE80211_ADDR_LEN])
192{
193 struct ieee80211_mesh_state *ms = vap->iv_mesh;
194 struct ieee80211_mesh_route *rt;
195
196 MESH_RT_LOCK(ms);
156 TAILQ_FOREACH(rt, &ms->ms_routes, rt_next) {
157 if (IEEE80211_ADDR_EQ(dest, rt->rt_dest)) {
158 MESH_RT_UNLOCK(ms);
159 return rt;
160 }
161 }
197 rt = mesh_rt_find_locked(ms, dest);
162 MESH_RT_UNLOCK(ms);
198 MESH_RT_UNLOCK(ms);
163 return NULL;
199 return rt;
164}
165
166struct ieee80211_mesh_route *
167ieee80211_mesh_rt_add(struct ieee80211vap *vap,
168 const uint8_t dest[IEEE80211_ADDR_LEN])
169{
170 struct ieee80211_mesh_state *ms = vap->iv_mesh;
171 struct ieee80211_mesh_route *rt;
172
173 KASSERT(ieee80211_mesh_rt_find(vap, dest) == NULL,
174 ("%s: duplicate entry in the routing table", __func__));
175 KASSERT(!IEEE80211_ADDR_EQ(vap->iv_myaddr, dest),
176 ("%s: adding self to the routing table", __func__));
200}
201
202struct ieee80211_mesh_route *
203ieee80211_mesh_rt_add(struct ieee80211vap *vap,
204 const uint8_t dest[IEEE80211_ADDR_LEN])
205{
206 struct ieee80211_mesh_state *ms = vap->iv_mesh;
207 struct ieee80211_mesh_route *rt;
208
209 KASSERT(ieee80211_mesh_rt_find(vap, dest) == NULL,
210 ("%s: duplicate entry in the routing table", __func__));
211 KASSERT(!IEEE80211_ADDR_EQ(vap->iv_myaddr, dest),
212 ("%s: adding self to the routing table", __func__));
177 KASSERT(!IEEE80211_ADDR_EQ(broadcastaddr, dest),
178 ("%s: adding broadcast to the routing table", __func__));
179
213
180 rt = malloc(sizeof(struct ieee80211_mesh_route), M_80211_MESH_RT,
181 M_NOWAIT | M_ZERO);
182 IEEE80211_ADDR_COPY(rt->rt_dest, dest);
183 rt->rt_priv = malloc(ms->ms_ppath->mpp_privlen, M_80211_MESH_RT,
184 M_NOWAIT | M_ZERO);
185 MESH_RT_LOCK(ms);
214 MESH_RT_LOCK(ms);
186 TAILQ_INSERT_TAIL(&ms->ms_routes, rt, rt_next);
215 rt = mesh_rt_add_locked(ms, dest);
187 MESH_RT_UNLOCK(ms);
188 return rt;
189}
190
216 MESH_RT_UNLOCK(ms);
217 return rt;
218}
219
220/*
221 * Add a proxy route (as needed) for the specified destination.
222 */
191void
223void
224ieee80211_mesh_proxy_check(struct ieee80211vap *vap,
225 const uint8_t dest[IEEE80211_ADDR_LEN])
226{
227 struct ieee80211_mesh_state *ms = vap->iv_mesh;
228 struct ieee80211_mesh_route *rt;
229
230 MESH_RT_LOCK(ms);
231 rt = mesh_rt_find_locked(ms, dest);
232 if (rt == NULL) {
233 rt = mesh_rt_add_locked(ms, dest);
234 if (rt == NULL) {
235 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest,
236 "%s", "unable to add proxy entry");
237 vap->iv_stats.is_mesh_rtaddfailed++;
238 } else {
239 IEEE80211_ADDR_COPY(rt->rt_nexthop, vap->iv_myaddr);
240 rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID
241 | IEEE80211_MESHRT_FLAGS_PROXY;
242 }
243 /* XXX assert PROXY? */
244 } else if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
245 struct ieee80211com *ic = vap->iv_ic;
246 /*
247 * Fix existing entry created by received frames from
248 * stations that have some memory of dest. We also
249 * flush any frames held on the staging queue; delivering
250 * them is too much trouble right now.
251 */
252 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest,
253 "%s", "fix proxy entry");
254 IEEE80211_ADDR_COPY(rt->rt_nexthop, vap->iv_myaddr);
255 rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID
256 | IEEE80211_MESHRT_FLAGS_PROXY;
257 /* XXX belongs in hwmp */
258 ieee80211_ageq_drain_node(&ic->ic_stageq,
259 (void *)(uintptr_t) ieee80211_mac_hash(ic, dest));
260 /* XXX stat? */
261 }
262 MESH_RT_UNLOCK(ms);
263}
264
265static __inline void
266mesh_rt_del(struct ieee80211_mesh_state *ms, struct ieee80211_mesh_route *rt)
267{
268 TAILQ_REMOVE(&ms->ms_routes, rt, rt_next);
269 free(rt, M_80211_MESH_RT);
270}
271
272void
192ieee80211_mesh_rt_del(struct ieee80211vap *vap,
193 const uint8_t dest[IEEE80211_ADDR_LEN])
194{
195 struct ieee80211_mesh_state *ms = vap->iv_mesh;
196 struct ieee80211_mesh_route *rt, *next;
197
198 MESH_RT_LOCK(ms);
199 TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
200 if (IEEE80211_ADDR_EQ(rt->rt_dest, dest)) {
273ieee80211_mesh_rt_del(struct ieee80211vap *vap,
274 const uint8_t dest[IEEE80211_ADDR_LEN])
275{
276 struct ieee80211_mesh_state *ms = vap->iv_mesh;
277 struct ieee80211_mesh_route *rt, *next;
278
279 MESH_RT_LOCK(ms);
280 TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
281 if (IEEE80211_ADDR_EQ(rt->rt_dest, dest)) {
201 TAILQ_REMOVE(&ms->ms_routes, rt, rt_next);
202 free(rt->rt_priv, M_80211_MESH_RT);
203 free(rt, M_80211_MESH_RT);
282 mesh_rt_del(ms, rt);
204 MESH_RT_UNLOCK(ms);
205 return;
206 }
207 }
208 MESH_RT_UNLOCK(ms);
209}
210
211void
212ieee80211_mesh_rt_flush(struct ieee80211vap *vap)
213{
214 struct ieee80211_mesh_state *ms = vap->iv_mesh;
215 struct ieee80211_mesh_route *rt, *next;
216
217 if (ms == NULL)
218 return;
219 MESH_RT_LOCK(ms);
283 MESH_RT_UNLOCK(ms);
284 return;
285 }
286 }
287 MESH_RT_UNLOCK(ms);
288}
289
290void
291ieee80211_mesh_rt_flush(struct ieee80211vap *vap)
292{
293 struct ieee80211_mesh_state *ms = vap->iv_mesh;
294 struct ieee80211_mesh_route *rt, *next;
295
296 if (ms == NULL)
297 return;
298 MESH_RT_LOCK(ms);
299 TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next)
300 mesh_rt_del(ms, rt);
301 MESH_RT_UNLOCK(ms);
302}
303
304/*
305 * Flush expired routing entries, i.e. those in invalid state for
306 * some time.
307 */
308static void
309mesh_rt_flush_invalid(struct ieee80211vap *vap)
310{
311 struct ieee80211_mesh_state *ms = vap->iv_mesh;
312 struct ieee80211_mesh_route *rt, *next;
313 struct timeval tv, delta;
314
315 if (ms == NULL)
316 return;
317 getmicrouptime(&tv);
318 MESH_RT_LOCK(ms);
220 TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
319 TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
221 TAILQ_REMOVE(&ms->ms_routes, rt, rt_next);
222 free(rt->rt_priv, M_80211_MESH_RT);
223 free(rt, M_80211_MESH_RT);
320 delta = tv;
321 timevalsub(&delta, &rt->rt_crtime);
322 if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 &&
323 timevalcmp(&delta, &ms->ms_ppath->mpp_inact, >=))
324 mesh_rt_del(ms, rt);
224 }
225 MESH_RT_UNLOCK(ms);
226}
227
228#define N(a) (sizeof(a) / sizeof(a[0]))
229int
230ieee80211_mesh_register_proto_path(const struct ieee80211_mesh_proto_path *mpp)
231{

--- 144 unchanged lines hidden (view full) ---

376 args[0] = ni->ni_mlpid;
377 args[1] = ni->ni_mllid;
378 args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
379 ieee80211_send_action(ni,
380 IEEE80211_ACTION_CAT_MESHPEERING,
381 IEEE80211_ACTION_MESHPEERING_CLOSE,
382 args);
383 }
325 }
326 MESH_RT_UNLOCK(ms);
327}
328
329#define N(a) (sizeof(a) / sizeof(a[0]))
330int
331ieee80211_mesh_register_proto_path(const struct ieee80211_mesh_proto_path *mpp)
332{

--- 144 unchanged lines hidden (view full) ---

477 args[0] = ni->ni_mlpid;
478 args[1] = ni->ni_mllid;
479 args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
480 ieee80211_send_action(ni,
481 IEEE80211_ACTION_CAT_MESHPEERING,
482 IEEE80211_ACTION_MESHPEERING_CLOSE,
483 args);
484 }
384 callout_stop(&ni->ni_mltimer);
485 callout_drain(&ni->ni_mltimer);
385 /* XXX belongs in hwmp */
386 ieee80211_ageq_drain_node(&ic->ic_stageq,
387 (void *)(uintptr_t) ieee80211_mac_hash(ic, ni->ni_macaddr));
388}
389
390static void
391mesh_vdetach(struct ieee80211vap *vap)
392{
393 struct ieee80211_mesh_state *ms = vap->iv_mesh;
394
486 /* XXX belongs in hwmp */
487 ieee80211_ageq_drain_node(&ic->ic_stageq,
488 (void *)(uintptr_t) ieee80211_mac_hash(ic, ni->ni_macaddr));
489}
490
491static void
492mesh_vdetach(struct ieee80211vap *vap)
493{
494 struct ieee80211_mesh_state *ms = vap->iv_mesh;
495
496 callout_drain(&ms->ms_cleantimer);
395 ieee80211_iterate_nodes(&vap->iv_ic->ic_sta, mesh_vdetach_peers,
396 NULL);
397 ieee80211_mesh_rt_flush(vap);
398 mtx_destroy(&ms->ms_rt_lock);
399 ms->ms_ppath->mpp_vdetach(vap);
400 free(vap->iv_mesh, M_80211_VAP);
401 vap->iv_mesh = NULL;
402}

--- 5 unchanged lines hidden (view full) ---

408 vap->iv_newstate = mesh_newstate;
409 vap->iv_input = mesh_input;
410 vap->iv_opdetach = mesh_vdetach;
411 vap->iv_recv_mgmt = mesh_recv_mgmt;
412 ms = malloc(sizeof(struct ieee80211_mesh_state), M_80211_VAP,
413 M_NOWAIT | M_ZERO);
414 if (ms == NULL) {
415 printf("%s: couldn't alloc MBSS state\n", __func__);
497 ieee80211_iterate_nodes(&vap->iv_ic->ic_sta, mesh_vdetach_peers,
498 NULL);
499 ieee80211_mesh_rt_flush(vap);
500 mtx_destroy(&ms->ms_rt_lock);
501 ms->ms_ppath->mpp_vdetach(vap);
502 free(vap->iv_mesh, M_80211_VAP);
503 vap->iv_mesh = NULL;
504}

--- 5 unchanged lines hidden (view full) ---

510 vap->iv_newstate = mesh_newstate;
511 vap->iv_input = mesh_input;
512 vap->iv_opdetach = mesh_vdetach;
513 vap->iv_recv_mgmt = mesh_recv_mgmt;
514 ms = malloc(sizeof(struct ieee80211_mesh_state), M_80211_VAP,
515 M_NOWAIT | M_ZERO);
516 if (ms == NULL) {
517 printf("%s: couldn't alloc MBSS state\n", __func__);
416 return;
518 return;
417 }
418 vap->iv_mesh = ms;
419 ms->ms_seq = 0;
420 ms->ms_flags = (IEEE80211_MESHFLAGS_AP | IEEE80211_MESHFLAGS_FWD);
421 ms->ms_ttl = IEEE80211_MESH_DEFAULT_TTL;
422 TAILQ_INIT(&ms->ms_routes);
423 mtx_init(&ms->ms_rt_lock, "MBSS", "802.11s routing table", MTX_DEF);
519 }
520 vap->iv_mesh = ms;
521 ms->ms_seq = 0;
522 ms->ms_flags = (IEEE80211_MESHFLAGS_AP | IEEE80211_MESHFLAGS_FWD);
523 ms->ms_ttl = IEEE80211_MESH_DEFAULT_TTL;
524 TAILQ_INIT(&ms->ms_routes);
525 mtx_init(&ms->ms_rt_lock, "MBSS", "802.11s routing table", MTX_DEF);
526 callout_init(&ms->ms_cleantimer, CALLOUT_MPSAFE);
424 mesh_select_proto_metric(vap, "AIRTIME");
425 KASSERT(ms->ms_pmetric, ("ms_pmetric == NULL"));
426 mesh_select_proto_path(vap, "HWMP");
427 KASSERT(ms->ms_ppath, ("ms_ppath == NULL"));
428 ms->ms_ppath->mpp_vattach(vap);
429}
430
431/*

--- 12 unchanged lines hidden (view full) ---

444 ostate = vap->iv_state;
445 IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s (%d)\n",
446 __func__, ieee80211_state_name[ostate],
447 ieee80211_state_name[nstate], arg);
448 vap->iv_state = nstate; /* state transition */
449 if (ostate != IEEE80211_S_SCAN)
450 ieee80211_cancel_scan(vap); /* background scan */
451 ni = vap->iv_bss; /* NB: no reference held */
527 mesh_select_proto_metric(vap, "AIRTIME");
528 KASSERT(ms->ms_pmetric, ("ms_pmetric == NULL"));
529 mesh_select_proto_path(vap, "HWMP");
530 KASSERT(ms->ms_ppath, ("ms_ppath == NULL"));
531 ms->ms_ppath->mpp_vattach(vap);
532}
533
534/*

--- 12 unchanged lines hidden (view full) ---

547 ostate = vap->iv_state;
548 IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s (%d)\n",
549 __func__, ieee80211_state_name[ostate],
550 ieee80211_state_name[nstate], arg);
551 vap->iv_state = nstate; /* state transition */
552 if (ostate != IEEE80211_S_SCAN)
553 ieee80211_cancel_scan(vap); /* background scan */
554 ni = vap->iv_bss; /* NB: no reference held */
452 /* Flush the routing table */
453 if (nstate != IEEE80211_S_INIT && ostate == IEEE80211_S_INIT)
454 ieee80211_mesh_rt_flush(vap);
555 if (nstate != IEEE80211_S_RUN && ostate == IEEE80211_S_RUN)
556 callout_drain(&ms->ms_cleantimer);
455 switch (nstate) {
456 case IEEE80211_S_INIT:
457 switch (ostate) {
458 case IEEE80211_S_SCAN:
459 ieee80211_cancel_scan(vap);
460 break;
461 case IEEE80211_S_CAC:
462 ieee80211_dfs_cac_stop(vap);
463 break;
464 case IEEE80211_S_RUN:
465 ieee80211_iterate_nodes(&ic->ic_sta,
466 mesh_vdetach_peers, NULL);
467 break;
468 default:
469 break;
470 }
471 if (ostate != IEEE80211_S_INIT) {
472 /* NB: optimize INIT -> INIT case */
473 ieee80211_reset_bss(vap);
557 switch (nstate) {
558 case IEEE80211_S_INIT:
559 switch (ostate) {
560 case IEEE80211_S_SCAN:
561 ieee80211_cancel_scan(vap);
562 break;
563 case IEEE80211_S_CAC:
564 ieee80211_dfs_cac_stop(vap);
565 break;
566 case IEEE80211_S_RUN:
567 ieee80211_iterate_nodes(&ic->ic_sta,
568 mesh_vdetach_peers, NULL);
569 break;
570 default:
571 break;
572 }
573 if (ostate != IEEE80211_S_INIT) {
574 /* NB: optimize INIT -> INIT case */
575 ieee80211_reset_bss(vap);
576 ieee80211_mesh_rt_flush(vap);
474 }
475 break;
476 case IEEE80211_S_SCAN:
477 switch (ostate) {
478 case IEEE80211_S_INIT:
479 if (vap->iv_des_chan != IEEE80211_CHAN_ANYC &&
480 !IEEE80211_IS_CHAN_RADAR(vap->iv_des_chan) &&
481 ms->ms_idlen != 0) {

--- 86 unchanged lines hidden (view full) ---

568 ieee80211_chan2ieee(ic, ic->ic_curchan));
569 }
570#endif
571 break;
572 default:
573 break;
574 }
575 ieee80211_node_authorize(vap->iv_bss);
577 }
578 break;
579 case IEEE80211_S_SCAN:
580 switch (ostate) {
581 case IEEE80211_S_INIT:
582 if (vap->iv_des_chan != IEEE80211_CHAN_ANYC &&
583 !IEEE80211_IS_CHAN_RADAR(vap->iv_des_chan) &&
584 ms->ms_idlen != 0) {

--- 86 unchanged lines hidden (view full) ---

671 ieee80211_chan2ieee(ic, ic->ic_curchan));
672 }
673#endif
674 break;
675 default:
676 break;
677 }
678 ieee80211_node_authorize(vap->iv_bss);
679 callout_reset(&ms->ms_cleantimer,
680 msecs_to_ticks(ms->ms_ppath->mpp_inact.tv_sec * 1000 +
681 ms->ms_ppath->mpp_inact.tv_usec / 1000),
682 mesh_rt_cleanup_cb, vap);
576 break;
577 default:
578 break;
579 }
683 break;
684 default:
685 break;
686 }
580
581 /* NB: ostate not nstate */
582 ms->ms_ppath->mpp_newstate(vap, ostate, arg);
687 /* NB: ostate not nstate */
688 ms->ms_ppath->mpp_newstate(vap, ostate, arg);
583
584 return 0;
585}
586
689 return 0;
690}
691
692static void
693mesh_rt_cleanup_cb(void *arg)
694{
695 struct ieee80211vap *vap = arg;
696 struct ieee80211_mesh_state *ms = vap->iv_mesh;
697
698 mesh_rt_flush_invalid(vap);
699 callout_reset(&ms->ms_cleantimer,
700 msecs_to_ticks(ms->ms_ppath->mpp_inact.tv_sec * 1000 +
701 ms->ms_ppath->mpp_inact.tv_usec / 1000),
702 mesh_rt_cleanup_cb, vap);
703}
704
705
587/*
588 * Helper function to note the Mesh Peer Link FSM change.
589 */
590static void
591mesh_linkchange(struct ieee80211_node *ni, enum ieee80211_mesh_mlstate state)
592{
593 struct ieee80211vap *vap = ni->ni_vap;
594 struct ieee80211_mesh_state *ms = vap->iv_mesh;

--- 17 unchanged lines hidden (view full) ---

612 KASSERT(ms->ms_neighbors < 65535, ("neighbor count overflow"));
613 ms->ms_neighbors++;
614 } else if (ni->ni_mlstate == IEEE80211_NODE_MESH_ESTABLISHED &&
615 state != IEEE80211_NODE_MESH_ESTABLISHED) {
616 KASSERT(ms->ms_neighbors > 0, ("neighbor count 0"));
617 ms->ms_neighbors--;
618 }
619 ni->ni_mlstate = state;
706/*
707 * Helper function to note the Mesh Peer Link FSM change.
708 */
709static void
710mesh_linkchange(struct ieee80211_node *ni, enum ieee80211_mesh_mlstate state)
711{
712 struct ieee80211vap *vap = ni->ni_vap;
713 struct ieee80211_mesh_state *ms = vap->iv_mesh;

--- 17 unchanged lines hidden (view full) ---

731 KASSERT(ms->ms_neighbors < 65535, ("neighbor count overflow"));
732 ms->ms_neighbors++;
733 } else if (ni->ni_mlstate == IEEE80211_NODE_MESH_ESTABLISHED &&
734 state != IEEE80211_NODE_MESH_ESTABLISHED) {
735 KASSERT(ms->ms_neighbors > 0, ("neighbor count 0"));
736 ms->ms_neighbors--;
737 }
738 ni->ni_mlstate = state;
620 if (state == IEEE80211_NODE_MESH_HOLDING)
739 switch (state) {
740 case IEEE80211_NODE_MESH_HOLDING:
621 ms->ms_ppath->mpp_peerdown(ni);
741 ms->ms_ppath->mpp_peerdown(ni);
742 break;
743 case IEEE80211_NODE_MESH_ESTABLISHED:
744 ieee80211_mesh_discover(vap, ni->ni_macaddr, NULL);
745 break;
746 default:
747 break;
748 }
622}
623
624/*
625 * Helper function to generate a unique local ID required for mesh
626 * peer establishment.
627 */
628static void
629mesh_checkid(void *arg, struct ieee80211_node *ni)

--- 25 unchanged lines hidden (view full) ---

655static int
656mesh_checkpseq(struct ieee80211vap *vap,
657 const uint8_t source[IEEE80211_ADDR_LEN], uint32_t seq)
658{
659 struct ieee80211_mesh_route *rt;
660
661 rt = ieee80211_mesh_rt_find(vap, source);
662 if (rt == NULL) {
749}
750
751/*
752 * Helper function to generate a unique local ID required for mesh
753 * peer establishment.
754 */
755static void
756mesh_checkid(void *arg, struct ieee80211_node *ni)

--- 25 unchanged lines hidden (view full) ---

782static int
783mesh_checkpseq(struct ieee80211vap *vap,
784 const uint8_t source[IEEE80211_ADDR_LEN], uint32_t seq)
785{
786 struct ieee80211_mesh_route *rt;
787
788 rt = ieee80211_mesh_rt_find(vap, source);
789 if (rt == NULL) {
790 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, source,
791 "add mcast route, mesh seqno %d", seq);
663 rt = ieee80211_mesh_rt_add(vap, source);
792 rt = ieee80211_mesh_rt_add(vap, source);
664 rt->rt_lastmseq = seq;
793 if (rt != NULL)
794 rt->rt_lastmseq = seq;
665 return 0;
666 }
667 if (IEEE80211_MESH_SEQ_GEQ(rt->rt_lastmseq, seq)) {
668 return 1;
669 } else {
670 rt->rt_lastmseq = seq;
671 return 0;
672 }

--- 6 unchanged lines hidden (view full) ---

679mesh_find_txnode(struct ieee80211vap *vap,
680 const uint8_t dest[IEEE80211_ADDR_LEN])
681{
682 struct ieee80211_mesh_route *rt;
683
684 rt = ieee80211_mesh_rt_find(vap, dest);
685 if (rt == NULL)
686 return NULL;
795 return 0;
796 }
797 if (IEEE80211_MESH_SEQ_GEQ(rt->rt_lastmseq, seq)) {
798 return 1;
799 } else {
800 rt->rt_lastmseq = seq;
801 return 0;
802 }

--- 6 unchanged lines hidden (view full) ---

809mesh_find_txnode(struct ieee80211vap *vap,
810 const uint8_t dest[IEEE80211_ADDR_LEN])
811{
812 struct ieee80211_mesh_route *rt;
813
814 rt = ieee80211_mesh_rt_find(vap, dest);
815 if (rt == NULL)
816 return NULL;
817 if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 ||
818 (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY)) {
819 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest,
820 "%s: !valid or proxy, flags 0x%x", __func__, rt->rt_flags);
821 /* XXX stat */
822 return NULL;
823 }
687 return ieee80211_find_txnode(vap, rt->rt_nexthop);
688}
689
690/*
691 * Forward the specified frame.
692 * Decrement the TTL and set TA to our MAC address.
693 */
694static void

--- 57 unchanged lines hidden (view full) ---

752 IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh,
753 "%s", "frame not fwd'd, no path");
754 vap->iv_stats.is_mesh_fwd_nopath++;
755 m_freem(mcopy);
756 return;
757 }
758 IEEE80211_ADDR_COPY(whcopy->i_addr1, ni->ni_macaddr);
759 }
824 return ieee80211_find_txnode(vap, rt->rt_nexthop);
825}
826
827/*
828 * Forward the specified frame.
829 * Decrement the TTL and set TA to our MAC address.
830 */
831static void

--- 57 unchanged lines hidden (view full) ---

889 IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh,
890 "%s", "frame not fwd'd, no path");
891 vap->iv_stats.is_mesh_fwd_nopath++;
892 m_freem(mcopy);
893 return;
894 }
895 IEEE80211_ADDR_COPY(whcopy->i_addr1, ni->ni_macaddr);
896 }
760 IEEE80211_NOTE(vap, IEEE80211_MSG_MESH, ni,
761 "fwd %s frame from %s ttl %d",
762 IEEE80211_IS_MULTICAST(wh->i_addr1) ? "mcast" : "ucast",
763 ether_sprintf(wh->i_addr3), mccopy->mc_ttl);
764
765 KASSERT(mccopy->mc_ttl > 0, ("%s called with wrong ttl", __func__));
766 mccopy->mc_ttl--;
767
768 /* XXX calculate priority so drivers can find the tx queue */
769 M_WME_SETAC(mcopy, WME_AC_BE);
770
771 /* XXX do we know m_nextpkt is NULL? */
772 mcopy->m_pkthdr.rcvif = (void *) ni;
773 err = parent->if_transmit(parent, mcopy);
774 if (err != 0) {
775 /* NB: IFQ_HANDOFF reclaims mbuf */
776 ieee80211_free_node(ni);
777 } else {
778 ifp->if_opackets++;
779 }
780}
781
897 KASSERT(mccopy->mc_ttl > 0, ("%s called with wrong ttl", __func__));
898 mccopy->mc_ttl--;
899
900 /* XXX calculate priority so drivers can find the tx queue */
901 M_WME_SETAC(mcopy, WME_AC_BE);
902
903 /* XXX do we know m_nextpkt is NULL? */
904 mcopy->m_pkthdr.rcvif = (void *) ni;
905 err = parent->if_transmit(parent, mcopy);
906 if (err != 0) {
907 /* NB: IFQ_HANDOFF reclaims mbuf */
908 ieee80211_free_node(ni);
909 } else {
910 ifp->if_opackets++;
911 }
912}
913
914static struct mbuf *
915mesh_decap(struct ieee80211vap *vap, struct mbuf *m, int hdrlen, int meshdrlen)
916{
917#define WHDIR(wh) ((wh)->i_fc[1] & IEEE80211_FC1_DIR_MASK)
918 uint8_t b[sizeof(struct ieee80211_qosframe_addr4) +
919 sizeof(struct ieee80211_meshcntl_ae11)];
920 const struct ieee80211_qosframe_addr4 *wh;
921 const struct ieee80211_meshcntl_ae10 *mc;
922 struct ether_header *eh;
923 struct llc *llc;
924 int ae;
925
926 if (m->m_len < hdrlen + sizeof(*llc) &&
927 (m = m_pullup(m, hdrlen + sizeof(*llc))) == NULL) {
928 IEEE80211_DPRINTF(vap, IEEE80211_MSG_ANY,
929 "discard data frame: %s", "m_pullup failed");
930 vap->iv_stats.is_rx_tooshort++;
931 return NULL;
932 }
933 memcpy(b, mtod(m, caddr_t), hdrlen);
934 wh = (const struct ieee80211_qosframe_addr4 *)&b[0];
935 mc = (const struct ieee80211_meshcntl_ae10 *)&b[hdrlen - meshdrlen];
936 KASSERT(WHDIR(wh) == IEEE80211_FC1_DIR_FROMDS ||
937 WHDIR(wh) == IEEE80211_FC1_DIR_DSTODS,
938 ("bogus dir, fc 0x%x:0x%x", wh->i_fc[0], wh->i_fc[1]));
939
940 llc = (struct llc *)(mtod(m, caddr_t) + hdrlen);
941 if (llc->llc_dsap == LLC_SNAP_LSAP && llc->llc_ssap == LLC_SNAP_LSAP &&
942 llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 &&
943 llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0 &&
944 /* NB: preserve AppleTalk frames that have a native SNAP hdr */
945 !(llc->llc_snap.ether_type == htons(ETHERTYPE_AARP) ||
946 llc->llc_snap.ether_type == htons(ETHERTYPE_IPX))) {
947 m_adj(m, hdrlen + sizeof(struct llc) - sizeof(*eh));
948 llc = NULL;
949 } else {
950 m_adj(m, hdrlen - sizeof(*eh));
951 }
952 eh = mtod(m, struct ether_header *);
953 ae = mc->mc_flags & 3;
954 if (WHDIR(wh) == IEEE80211_FC1_DIR_FROMDS) {
955 IEEE80211_ADDR_COPY(eh->ether_dhost, wh->i_addr1);
956 if (ae == 0) {
957 IEEE80211_ADDR_COPY(eh->ether_shost, wh->i_addr3);
958 } else if (ae == 1) {
959 IEEE80211_ADDR_COPY(eh->ether_shost, mc->mc_addr4);
960 } else {
961 IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
962 (const struct ieee80211_frame *)wh, NULL,
963 "bad AE %d", ae);
964 vap->iv_stats.is_mesh_badae++;
965 m_freem(m);
966 return NULL;
967 }
968 } else {
969 if (ae == 0) {
970 IEEE80211_ADDR_COPY(eh->ether_dhost, wh->i_addr3);
971 IEEE80211_ADDR_COPY(eh->ether_shost, wh->i_addr4);
972 } else if (ae == 2) {
973 IEEE80211_ADDR_COPY(eh->ether_dhost, mc->mc_addr4);
974 IEEE80211_ADDR_COPY(eh->ether_shost, mc->mc_addr5);
975 } else {
976 IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
977 (const struct ieee80211_frame *)wh, NULL,
978 "bad AE %d", ae);
979 vap->iv_stats.is_mesh_badae++;
980 m_freem(m);
981 return NULL;
982 }
983 }
984#ifdef ALIGNED_POINTER
985 if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), uint32_t)) {
986 m = ieee80211_realign(vap, m, sizeof(*eh));
987 if (m == NULL)
988 return NULL;
989 }
990#endif /* ALIGNED_POINTER */
991 if (llc != NULL) {
992 eh = mtod(m, struct ether_header *);
993 eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh));
994 }
995 return m;
996#undef WDIR
997}
998
999/*
1000 * Return non-zero if the unicast mesh data frame should be processed
1001 * locally. Frames that are not proxy'd have our address, otherwise
1002 * we need to consult the routing table to look for a proxy entry.
1003 */
1004static __inline int
1005mesh_isucastforme(struct ieee80211vap *vap, const struct ieee80211_frame *wh,
1006 const struct ieee80211_meshcntl *mc)
1007{
1008 int ae = mc->mc_flags & 3;
1009
1010 KASSERT((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS,
1011 ("bad dir 0x%x:0x%x", wh->i_fc[0], wh->i_fc[1]));
1012 KASSERT(ae == 0 || ae == 2, ("bad AE %d", ae));
1013 if (ae == 2) { /* ucast w/ proxy */
1014 const struct ieee80211_meshcntl_ae10 *mc10 =
1015 (const struct ieee80211_meshcntl_ae10 *) mc;
1016 struct ieee80211_mesh_route *rt =
1017 ieee80211_mesh_rt_find(vap, mc10->mc_addr4);
1018 /* check for proxy route to ourself */
1019 return (rt != NULL &&
1020 (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY));
1021 } else /* ucast w/o proxy */
1022 return IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_myaddr);
1023}
1024
782static int
783mesh_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
784{
785#define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0)
786#define HAS_SEQ(type) ((type & 0x4) == 0)
787 struct ieee80211vap *vap = ni->ni_vap;
788 struct ieee80211com *ic = ni->ni_ic;
789 struct ifnet *ifp = vap->iv_ifp;
790 struct ieee80211_frame *wh;
791 const struct ieee80211_meshcntl *mc;
1025static int
1026mesh_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
1027{
1028#define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0)
1029#define HAS_SEQ(type) ((type & 0x4) == 0)
1030 struct ieee80211vap *vap = ni->ni_vap;
1031 struct ieee80211com *ic = ni->ni_ic;
1032 struct ifnet *ifp = vap->iv_ifp;
1033 struct ieee80211_frame *wh;
1034 const struct ieee80211_meshcntl *mc;
792 int hdrspace, need_tap;
1035 int hdrspace, meshdrlen, need_tap;
793 uint8_t dir, type, subtype, qos;
794 uint32_t seq;
795 uint8_t *addr;
796 ieee80211_seq rxseq;
797
798 KASSERT(ni != NULL, ("null node"));
799 ni->ni_inact = ni->ni_inact_reload;
800

--- 98 unchanged lines hidden (view full) ---

899 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
900 ni->ni_macaddr, NULL,
901 "data too short: expecting %u", hdrspace);
902 vap->iv_stats.is_rx_tooshort++;
903 goto out; /* XXX */
904 }
905 /*
906 * Now calculate the full extent of the headers. Note
1036 uint8_t dir, type, subtype, qos;
1037 uint32_t seq;
1038 uint8_t *addr;
1039 ieee80211_seq rxseq;
1040
1041 KASSERT(ni != NULL, ("null node"));
1042 ni->ni_inact = ni->ni_inact_reload;
1043

--- 98 unchanged lines hidden (view full) ---

1142 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
1143 ni->ni_macaddr, NULL,
1144 "data too short: expecting %u", hdrspace);
1145 vap->iv_stats.is_rx_tooshort++;
1146 goto out; /* XXX */
1147 }
1148 /*
1149 * Now calculate the full extent of the headers. Note
907 * ieee80211_decap will pull up anything we didn't get
1150 * mesh_decap will pull up anything we didn't get
908 * above when it strips the 802.11 headers.
909 */
910 mc = (const struct ieee80211_meshcntl *)
911 (mtod(m, const uint8_t *) + hdrspace);
1151 * above when it strips the 802.11 headers.
1152 */
1153 mc = (const struct ieee80211_meshcntl *)
1154 (mtod(m, const uint8_t *) + hdrspace);
912 hdrspace += sizeof(struct ieee80211_meshcntl) +
1155 meshdrlen = sizeof(struct ieee80211_meshcntl) +
913 (mc->mc_flags & 3) * IEEE80211_ADDR_LEN;
1156 (mc->mc_flags & 3) * IEEE80211_ADDR_LEN;
1157 hdrspace += meshdrlen;
914 seq = LE_READ_4(mc->mc_seq);
915 if (IEEE80211_IS_MULTICAST(wh->i_addr1))
916 addr = wh->i_addr3;
917 else
918 addr = ((struct ieee80211_qosframe_addr4 *)wh)->i_addr4;
919 if (IEEE80211_ADDR_EQ(vap->iv_myaddr, addr)) {
920 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
921 addr, "data", "%s", "not to me");

--- 8 unchanged lines hidden (view full) ---

930 goto out;
931 }
932
933 /*
934 * Potentially forward packet. See table s36 (p140)
935 * for the rules. XXX tap fwd'd packets not for us?
936 */
937 if (dir == IEEE80211_FC1_DIR_FROMDS ||
1158 seq = LE_READ_4(mc->mc_seq);
1159 if (IEEE80211_IS_MULTICAST(wh->i_addr1))
1160 addr = wh->i_addr3;
1161 else
1162 addr = ((struct ieee80211_qosframe_addr4 *)wh)->i_addr4;
1163 if (IEEE80211_ADDR_EQ(vap->iv_myaddr, addr)) {
1164 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
1165 addr, "data", "%s", "not to me");

--- 8 unchanged lines hidden (view full) ---

1174 goto out;
1175 }
1176
1177 /*
1178 * Potentially forward packet. See table s36 (p140)
1179 * for the rules. XXX tap fwd'd packets not for us?
1180 */
1181 if (dir == IEEE80211_FC1_DIR_FROMDS ||
938 !IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_myaddr)) {
1182 !mesh_isucastforme(vap, wh, mc)) {
939 mesh_forward(vap, m, mc);
940 if (dir == IEEE80211_FC1_DIR_DSTODS)
941 goto out;
942 /* NB: fall thru to deliver mcast frames locally */
943 }
944
945 /*
946 * Save QoS bits for use below--before we strip the header.

--- 18 unchanged lines hidden (view full) ---

965
966 if (ieee80211_radiotap_active_vap(vap))
967 ieee80211_radiotap_rx(vap, m);
968 need_tap = 0;
969
970 /*
971 * Finally, strip the 802.11 header.
972 */
1183 mesh_forward(vap, m, mc);
1184 if (dir == IEEE80211_FC1_DIR_DSTODS)
1185 goto out;
1186 /* NB: fall thru to deliver mcast frames locally */
1187 }
1188
1189 /*
1190 * Save QoS bits for use below--before we strip the header.

--- 18 unchanged lines hidden (view full) ---

1209
1210 if (ieee80211_radiotap_active_vap(vap))
1211 ieee80211_radiotap_rx(vap, m);
1212 need_tap = 0;
1213
1214 /*
1215 * Finally, strip the 802.11 header.
1216 */
973 m = ieee80211_decap(vap, m, hdrspace);
1217 m = mesh_decap(vap, m, hdrspace, meshdrlen);
974 if (m == NULL) {
975 /* XXX mask bit to check for both */
976 /* don't count Null data frames as errors */
977 if (subtype == IEEE80211_FC0_SUBTYPE_NODATA ||
978 subtype == IEEE80211_FC0_SUBTYPE_QOS_NULL)
979 goto out;
980 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
981 ni->ni_macaddr, "data", "%s", "decap error");
982 vap->iv_stats.is_rx_decap++;
983 IEEE80211_NODE_STAT(ni, rx_decap);
984 goto err;
985 }
986 if (qos & IEEE80211_QOS_AMSDU) {
987 m = ieee80211_decap_amsdu(ni, m);
988 if (m == NULL)
989 return IEEE80211_FC0_TYPE_DATA;
1218 if (m == NULL) {
1219 /* XXX mask bit to check for both */
1220 /* don't count Null data frames as errors */
1221 if (subtype == IEEE80211_FC0_SUBTYPE_NODATA ||
1222 subtype == IEEE80211_FC0_SUBTYPE_QOS_NULL)
1223 goto out;
1224 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
1225 ni->ni_macaddr, "data", "%s", "decap error");
1226 vap->iv_stats.is_rx_decap++;
1227 IEEE80211_NODE_STAT(ni, rx_decap);
1228 goto err;
1229 }
1230 if (qos & IEEE80211_QOS_AMSDU) {
1231 m = ieee80211_decap_amsdu(ni, m);
1232 if (m == NULL)
1233 return IEEE80211_FC0_TYPE_DATA;
990 } else {
991#ifdef IEEE80211_SUPPORT_SUPERG
992 m = ieee80211_decap_fastframe(vap, ni, m);
993 if (m == NULL)
994 return IEEE80211_FC0_TYPE_DATA;
995#endif
996 }
1234 }
997 ieee80211_deliver_data(vap, ni, m);
998 return type;
999 case IEEE80211_FC0_TYPE_MGT:
1000 vap->iv_stats.is_rx_mgmt++;
1001 IEEE80211_NODE_STAT(ni, rx_mgmt);
1002 if (dir != IEEE80211_FC1_DIR_NODS) {
1003 IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1004 wh, "mgt", "incorrect dir 0x%x", dir);

--- 957 unchanged lines hidden (view full) ---

1962 ni->ni_mltval += r % ni->ni_mltval;
1963 callout_reset(&ni->ni_mltimer, ni->ni_mltval, mesh_peer_timeout_cb,
1964 ni);
1965}
1966
1967static __inline void
1968mesh_peer_timeout_stop(struct ieee80211_node *ni)
1969{
1235 ieee80211_deliver_data(vap, ni, m);
1236 return type;
1237 case IEEE80211_FC0_TYPE_MGT:
1238 vap->iv_stats.is_rx_mgmt++;
1239 IEEE80211_NODE_STAT(ni, rx_mgmt);
1240 if (dir != IEEE80211_FC1_DIR_NODS) {
1241 IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1242 wh, "mgt", "incorrect dir 0x%x", dir);

--- 957 unchanged lines hidden (view full) ---

2200 ni->ni_mltval += r % ni->ni_mltval;
2201 callout_reset(&ni->ni_mltimer, ni->ni_mltval, mesh_peer_timeout_cb,
2202 ni);
2203}
2204
2205static __inline void
2206mesh_peer_timeout_stop(struct ieee80211_node *ni)
2207{
1970 callout_stop(&ni->ni_mltimer);
2208 callout_drain(&ni->ni_mltimer);
1971}
1972
1973/*
1974 * Mesh Peer Link Management FSM timeout handling.
1975 */
1976static void
1977mesh_peer_timeout_cb(void *arg)
1978{

--- 417 unchanged lines hidden (view full) ---

2396 len += sizeof(*imr);
2397 }
2398 MESH_RT_UNLOCK(ms);
2399 if (len > ireq->i_len || ireq->i_len < sizeof(*imr)) {
2400 ireq->i_len = len;
2401 return ENOMEM;
2402 }
2403 ireq->i_len = len;
2209}
2210
2211/*
2212 * Mesh Peer Link Management FSM timeout handling.
2213 */
2214static void
2215mesh_peer_timeout_cb(void *arg)
2216{

--- 417 unchanged lines hidden (view full) ---

2634 len += sizeof(*imr);
2635 }
2636 MESH_RT_UNLOCK(ms);
2637 if (len > ireq->i_len || ireq->i_len < sizeof(*imr)) {
2638 ireq->i_len = len;
2639 return ENOMEM;
2640 }
2641 ireq->i_len = len;
2642 /* XXX M_WAIT? */
2404 p = malloc(len, M_TEMP, M_NOWAIT | M_ZERO);
2405 if (p == NULL)
2406 return ENOMEM;
2407 off = 0;
2408 MESH_RT_LOCK(ms);
2409 TAILQ_FOREACH(rt, &ms->ms_routes, rt_next) {
2410 if (off >= len)
2411 break;
2412 imr = (struct ieee80211req_mesh_route *)
2413 (p + off);
2414 IEEE80211_ADDR_COPY(imr->imr_dest,
2415 rt->rt_dest);
2416 IEEE80211_ADDR_COPY(imr->imr_nexthop,
2417 rt->rt_nexthop);
2418 imr->imr_metric = rt->rt_metric;
2419 imr->imr_nhops = rt->rt_nhops;
2420 imr->imr_lifetime = rt->rt_lifetime;
2643 p = malloc(len, M_TEMP, M_NOWAIT | M_ZERO);
2644 if (p == NULL)
2645 return ENOMEM;
2646 off = 0;
2647 MESH_RT_LOCK(ms);
2648 TAILQ_FOREACH(rt, &ms->ms_routes, rt_next) {
2649 if (off >= len)
2650 break;
2651 imr = (struct ieee80211req_mesh_route *)
2652 (p + off);
2653 IEEE80211_ADDR_COPY(imr->imr_dest,
2654 rt->rt_dest);
2655 IEEE80211_ADDR_COPY(imr->imr_nexthop,
2656 rt->rt_nexthop);
2657 imr->imr_metric = rt->rt_metric;
2658 imr->imr_nhops = rt->rt_nhops;
2659 imr->imr_lifetime = rt->rt_lifetime;
2660 imr->imr_lastmseq = rt->rt_lastmseq;
2421 off += sizeof(*imr);
2422 }
2423 MESH_RT_UNLOCK(ms);
2424 error = copyout(p, (uint8_t *)ireq->i_data,
2425 ireq->i_len);
2426 free(p, M_TEMP);
2427 break;
2428 case IEEE80211_MESH_RTCMD_FLUSH:

--- 41 unchanged lines hidden (view full) ---

2470 return ENOSYS;
2471
2472 error = 0;
2473 switch (ireq->i_type) {
2474 case IEEE80211_IOC_MESH_ID:
2475 if (ireq->i_val != 0 || ireq->i_len > IEEE80211_MESHID_LEN)
2476 return EINVAL;
2477 error = copyin(ireq->i_data, tmpmeshid, ireq->i_len);
2661 off += sizeof(*imr);
2662 }
2663 MESH_RT_UNLOCK(ms);
2664 error = copyout(p, (uint8_t *)ireq->i_data,
2665 ireq->i_len);
2666 free(p, M_TEMP);
2667 break;
2668 case IEEE80211_MESH_RTCMD_FLUSH:

--- 41 unchanged lines hidden (view full) ---

2710 return ENOSYS;
2711
2712 error = 0;
2713 switch (ireq->i_type) {
2714 case IEEE80211_IOC_MESH_ID:
2715 if (ireq->i_val != 0 || ireq->i_len > IEEE80211_MESHID_LEN)
2716 return EINVAL;
2717 error = copyin(ireq->i_data, tmpmeshid, ireq->i_len);
2478 if (error)
2718 if (error != 0)
2479 break;
2480 memset(ms->ms_id, 0, IEEE80211_NWID_LEN);
2481 ms->ms_idlen = ireq->i_len;
2482 memcpy(ms->ms_id, tmpmeshid, ireq->i_len);
2719 break;
2720 memset(ms->ms_id, 0, IEEE80211_NWID_LEN);
2721 ms->ms_idlen = ireq->i_len;
2722 memcpy(ms->ms_id, tmpmeshid, ireq->i_len);
2723 error = ENETRESET;
2483 break;
2484 case IEEE80211_IOC_MESH_AP:
2485 if (ireq->i_val)
2486 ms->ms_flags |= IEEE80211_MESHFLAGS_AP;
2487 else
2488 ms->ms_flags &= ~IEEE80211_MESHFLAGS_AP;
2724 break;
2725 case IEEE80211_IOC_MESH_AP:
2726 if (ireq->i_val)
2727 ms->ms_flags |= IEEE80211_MESHFLAGS_AP;
2728 else
2729 ms->ms_flags &= ~IEEE80211_MESHFLAGS_AP;
2730 error = ENETRESET;
2489 break;
2490 case IEEE80211_IOC_MESH_FWRD:
2491 if (ireq->i_val)
2492 ms->ms_flags |= IEEE80211_MESHFLAGS_FWD;
2493 else
2494 ms->ms_flags &= ~IEEE80211_MESHFLAGS_FWD;
2495 break;
2496 case IEEE80211_IOC_MESH_TTL:

--- 7 unchanged lines hidden (view full) ---

2504 ieee80211_mesh_rt_flush(vap);
2505 break;
2506 case IEEE80211_MESH_RTCMD_ADD:
2507 if (IEEE80211_ADDR_EQ(vap->iv_myaddr, ireq->i_data) ||
2508 IEEE80211_ADDR_EQ(broadcastaddr, ireq->i_data))
2509 return EINVAL;
2510 error = copyin(ireq->i_data, &tmpaddr,
2511 IEEE80211_ADDR_LEN);
2731 break;
2732 case IEEE80211_IOC_MESH_FWRD:
2733 if (ireq->i_val)
2734 ms->ms_flags |= IEEE80211_MESHFLAGS_FWD;
2735 else
2736 ms->ms_flags &= ~IEEE80211_MESHFLAGS_FWD;
2737 break;
2738 case IEEE80211_IOC_MESH_TTL:

--- 7 unchanged lines hidden (view full) ---

2746 ieee80211_mesh_rt_flush(vap);
2747 break;
2748 case IEEE80211_MESH_RTCMD_ADD:
2749 if (IEEE80211_ADDR_EQ(vap->iv_myaddr, ireq->i_data) ||
2750 IEEE80211_ADDR_EQ(broadcastaddr, ireq->i_data))
2751 return EINVAL;
2752 error = copyin(ireq->i_data, &tmpaddr,
2753 IEEE80211_ADDR_LEN);
2512 if (!error)
2754 if (error == 0)
2513 ieee80211_mesh_discover(vap, tmpaddr, NULL);
2514 break;
2515 case IEEE80211_MESH_RTCMD_DELETE:
2516 ieee80211_mesh_rt_del(vap, ireq->i_data);
2517 break;
2518 default:
2519 return ENOSYS;
2520 }
2521 break;
2522 case IEEE80211_IOC_MESH_PR_METRIC:
2523 error = copyin(ireq->i_data, tmpproto, sizeof(tmpproto));
2755 ieee80211_mesh_discover(vap, tmpaddr, NULL);
2756 break;
2757 case IEEE80211_MESH_RTCMD_DELETE:
2758 ieee80211_mesh_rt_del(vap, ireq->i_data);
2759 break;
2760 default:
2761 return ENOSYS;
2762 }
2763 break;
2764 case IEEE80211_IOC_MESH_PR_METRIC:
2765 error = copyin(ireq->i_data, tmpproto, sizeof(tmpproto));
2524 if (!error)
2525 return mesh_select_proto_metric(vap, tmpproto);
2766 if (error == 0) {
2767 error = mesh_select_proto_metric(vap, tmpproto);
2768 if (error == 0)
2769 error = ENETRESET;
2770 }
2526 break;
2527 case IEEE80211_IOC_MESH_PR_PATH:
2528 error = copyin(ireq->i_data, tmpproto, sizeof(tmpproto));
2771 break;
2772 case IEEE80211_IOC_MESH_PR_PATH:
2773 error = copyin(ireq->i_data, tmpproto, sizeof(tmpproto));
2529 if (!error)
2530 return mesh_select_proto_path(vap, tmpproto);
2774 if (error == 0) {
2775 error = mesh_select_proto_path(vap, tmpproto);
2776 if (error == 0)
2777 error = ENETRESET;
2778 }
2531 break;
2532 default:
2533 return ENOSYS;
2534 }
2535 return error;
2536}
2537IEEE80211_IOCTL_SET(mesh, mesh_ioctl_set80211);
2779 break;
2780 default:
2781 return ENOSYS;
2782 }
2783 return error;
2784}
2785IEEE80211_IOCTL_SET(mesh, mesh_ioctl_set80211);