diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net80211/ieee80211_input.c | 4 | ||||
-rw-r--r-- | sys/net80211/ieee80211_proto.c | 37 | ||||
-rw-r--r-- | sys/net80211/ieee80211_var.h | 6 |
3 files changed, 46 insertions, 1 deletions
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index 69738ab..1c2fa86 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -1901,6 +1901,9 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0, /* record tsf of last beacon */ memcpy(ni->ni_tstamp.data, scan.tstamp, sizeof(ni->ni_tstamp)); + /* count beacon frame for s/w bmiss handling */ + ic->ic_swbmiss_count++; + ic->ic_bmiss_count = 0; if (ni->ni_erp != scan.erp) { IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC, "[%s] erp change: was 0x%x, now 0x%x\n", @@ -1944,7 +1947,6 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0, if (ic->ic_flags & IEEE80211_F_SCAN) ieee80211_add_scan(ic, &scan, wh, subtype, rssi, rstamp); - ic->ic_bmiss_count = 0; return; } /* diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c index 853ea60..bb755ed 100644 --- a/sys/net80211/ieee80211_proto.c +++ b/sys/net80211/ieee80211_proto.c @@ -98,6 +98,7 @@ ieee80211_proto_attach(struct ieee80211com *ic) ic->ic_fragthreshold = IEEE80211_FRAG_DEFAULT; ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE; ic->ic_bmiss_max = IEEE80211_BMISS_MAX; + callout_init(&ic->ic_swbmiss, CALLOUT_MPSAFE); ic->ic_mcast_rate = IEEE80211_MCAST_RATE_DEFAULT; ic->ic_protmode = IEEE80211_PROT_CTSONLY; ic->ic_roaming = IEEE80211_ROAMING_AUTO; @@ -855,6 +856,26 @@ ieee80211_beacon_miss(struct ieee80211com *ic) ieee80211_new_state(ic, IEEE80211_S_SCAN, 0); } +/* + * Software beacon miss handling. Check if any beacons + * were received in the last period. If not post a + * beacon miss; otherwise reset the counter. + */ +static void +ieee80211_swbmiss(void *arg) +{ + struct ieee80211com *ic = arg; + + if (ic->ic_swbmiss_count == 0) { + ieee80211_beacon_miss(ic); + if (ic->ic_bmiss_count == 0) /* don't re-arm timer */ + return; + } else + ic->ic_swbmiss_count = 0; + callout_reset(&ic->ic_swbmiss, ic->ic_swbmiss_period, + ieee80211_swbmiss, ic); +} + static void sta_disassoc(void *arg, struct ieee80211_node *ni) { @@ -888,6 +909,8 @@ ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg ieee80211_state_name[ostate], ieee80211_state_name[nstate]); ic->ic_state = nstate; /* state transition */ ni = ic->ic_bss; /* NB: no reference held */ + if (ic->ic_flags_ext & IEEE80211_FEXT_SWBMISS) + callout_stop(&ic->ic_swbmiss); switch (nstate) { case IEEE80211_S_INIT: switch (ostate) { @@ -1093,6 +1116,20 @@ ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg if_start(ifp); /* XXX not authorized yet */ break; } + if (ostate != IEEE80211_S_RUN && + ic->ic_opmode == IEEE80211_M_STA && + (ic->ic_flags_ext & IEEE80211_FEXT_SWBMISS)) { + /* + * Start s/w beacon miss timer for devices w/o + * hardware support. We fudge a bit here since + * we're doing this in software. + */ + ic->ic_swbmiss_period = IEEE80211_TU_TO_TICKS( + 2 * ic->ic_bmissthreshold * ni->ni_intval); + ic->ic_swbmiss_count = 0; + callout_reset(&ic->ic_swbmiss, ic->ic_swbmiss_period, + ieee80211_swbmiss, ic); + } /* * Start/stop the authenticator when operating as an * AP. We delay until here to allow configuration to diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index b36beea..f920f59 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -71,6 +71,7 @@ #define IEEE80211_BINTVAL_DEFAULT 100 /* default beacon interval (TU's) */ #define IEEE80211_BMISS_MAX 2 /* maximum consecutive bmiss allowed */ +#define IEEE80211_SWBMISS_THRESHOLD 50 /* s/w bmiss threshold (TU's) */ #define IEEE80211_PS_SLEEP 0x1 /* STA is in power saving mode */ #define IEEE80211_PS_MAX_QUEUE 50 /* maximum saved packets */ @@ -83,6 +84,7 @@ #define IEEE80211_MS_TO_TU(x) (((x) * 1024) / 1000) #define IEEE80211_TU_TO_MS(x) (((x) * 1000) / 1024) +#define IEEE80211_TU_TO_TICKS(x)(((x) * hz) / 1024) struct ieee80211_aclator; struct sysctl_ctx_list; @@ -147,6 +149,9 @@ struct ieee80211com { u_int8_t ic_bmissthreshold; u_int8_t ic_bmiss_count; /* current beacon miss count */ int ic_bmiss_max; /* max bmiss before scan */ + u_int16_t ic_swbmiss_count;/* beacons in last period */ + u_int16_t ic_swbmiss_period;/* s/w bmiss period */ + struct callout ic_swbmiss; /* s/w beacon miss timer */ struct ieee80211_node *(*ic_node_alloc)(struct ieee80211_node_table*); void (*ic_node_free)(struct ieee80211_node *); void (*ic_node_cleanup)(struct ieee80211_node *); @@ -247,6 +252,7 @@ struct ieee80211com { /* 0x00000006 reserved */ #define IEEE80211_FEXT_BGSCAN 0x00000008 /* STATUS: enable full bgscan completion */ #define IEEE80211_FEXT_ERPUPDATE 0x00000200 /* STATUS: update ERP element */ +#define IEEE80211_FEXT_SWBMISS 0x00000400 /* CONF: do bmiss in s/w */ /* ic_caps */ #define IEEE80211_C_WEP 0x00000001 /* CAPABILITY: WEP available */ |