From 2911d079c2167e81ddbbf13a22438cb4afd104c9 Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 12 Dec 2005 18:04:44 +0000 Subject: Add ieee80211_beacon_miss for processing sta mode beacon miss events in the 802.11 layer: we send a directed probe request frame to the current ap bmiss_max times (w/o answer) before scanning for a new ap. MFC after: 2 weeks --- sys/net80211/ieee80211_freebsd.c | 3 +++ sys/net80211/ieee80211_input.c | 1 + sys/net80211/ieee80211_proto.c | 38 ++++++++++++++++++++++++++++++++++++++ sys/net80211/ieee80211_proto.h | 1 + sys/net80211/ieee80211_var.h | 4 ++++ 5 files changed, 47 insertions(+) diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c index e05744a..4fa0207 100644 --- a/sys/net80211/ieee80211_freebsd.c +++ b/sys/net80211/ieee80211_freebsd.c @@ -126,6 +126,9 @@ ieee80211_sysctl_attach(struct ieee80211com *ic) SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "driver_caps", CTLFLAG_RW, &ic->ic_caps, 0, "driver capabilities"); + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "bmiss_max", CTLFLAG_RW, &ic->ic_bmiss_max, 0, + "consecutive beacon misses before scanning"); ic->ic_sysctl = ctx; } diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index 1b3c3fb..80a64d7 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -1942,6 +1942,7 @@ 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 8f3abd8..f7834f9 100644 --- a/sys/net80211/ieee80211_proto.c +++ b/sys/net80211/ieee80211_proto.c @@ -97,6 +97,7 @@ ieee80211_proto_attach(struct ieee80211com *ic) ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT; ic->ic_fragthreshold = IEEE80211_FRAG_DEFAULT; ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE; + ic->ic_bmiss_max = IEEE80211_BMISS_MAX; ic->ic_mcast_rate = IEEE80211_MCAST_RATE_DEFAULT; ic->ic_protmode = IEEE80211_PROT_CTSONLY; ic->ic_roaming = IEEE80211_ROAMING_AUTO; @@ -817,6 +818,43 @@ ieee80211_wme_updateparams(struct ieee80211com *ic) } } +void +ieee80211_beacon_miss(struct ieee80211com *ic) +{ + + if (ic->ic_flags & IEEE80211_F_SCAN) { + /* XXX check ic_curchan != ic_bsschan? */ + return; + } + IEEE80211_DPRINTF(ic, + IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, + "%s\n", "beacon miss"); + + /* + * Our handling is only meaningful for stations that are + * associated; any other conditions else will be handled + * through different means (e.g. the tx timeout on mgt frames). + */ + if (ic->ic_opmode != IEEE80211_M_STA || ic->ic_state != IEEE80211_S_RUN) + return; + + if (++ic->ic_bmiss_count < ic->ic_bmiss_max) { + /* + * Send a directed probe req before falling back to a scan; + * if we receive a response ic_bmiss_count will be reset. + * Some cards mistakenly report beacon miss so this avoids + * the expensive scan if the ap is still there. + */ + ieee80211_send_probereq(ic->ic_bss, ic->ic_myaddr, + ic->ic_bss->ni_bssid, ic->ic_bss->ni_bssid, + ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen, + ic->ic_opt_ie, ic->ic_opt_ie_len); + return; + } + ic->ic_bmiss_count = 0; + ieee80211_new_state(ic, IEEE80211_S_SCAN, 0); +} + static void sta_disassoc(void *arg, struct ieee80211_node *ni) { diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h index 694eff5b..ea05da8 100644 --- a/sys/net80211/ieee80211_proto.h +++ b/sys/net80211/ieee80211_proto.h @@ -218,6 +218,7 @@ void ieee80211_wme_updateparams_locked(struct ieee80211com *); #define ieee80211_new_state(_ic, _nstate, _arg) \ (((_ic)->ic_newstate)((_ic), (_nstate), (_arg))) +void ieee80211_beacon_miss(struct ieee80211com *); void ieee80211_print_essid(const u_int8_t *, int); void ieee80211_dump_pkt(const u_int8_t *, int, int, int); diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index b4be276..3c918f5 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -70,6 +70,8 @@ #define IEEE80211_BINTVAL_MIN 25 /* min beacon interval (TU's) */ #define IEEE80211_BINTVAL_DEFAULT 100 /* default beacon interval (TU's) */ +#define IEEE80211_BMISS_MAX 2 /* maximum consecutive bmiss allowed */ + #define IEEE80211_PS_SLEEP 0x1 /* STA is in power saving mode */ #define IEEE80211_PS_MAX_QUEUE 50 /* maximum saved packets */ @@ -142,6 +144,8 @@ struct ieee80211com { int ic_mcast_rate; /* rate for mcast frames */ u_int16_t ic_rtsthreshold; u_int16_t ic_fragthreshold; + u_int8_t ic_bmiss_count; /* current beacon miss count */ + int ic_bmiss_max; /* max bmiss before scan */ struct ieee80211_node *(*ic_node_alloc)(struct ieee80211_node_table*); void (*ic_node_free)(struct ieee80211_node *); void (*ic_node_cleanup)(struct ieee80211_node *); -- cgit v1.1