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); |