==== //depot/projects/wifi/sys/net80211/ieee80211.c#55 - /opt/sam_wifi/sys/net80211/ieee80211.c ==== --- /tmp/tmp.775.60 2007-07-15 22:07:45.000000000 +0800 +++ /opt/sam_wifi/sys/net80211/ieee80211.c 2007-07-15 21:58:12.000000000 +0800 @@ -120,6 +120,17 @@ ieee80211_remove_vap(struct ieee80211com mtx_unlock(&ieee80211_vap_mtx); } +void +ieee80211_iterate_vap(void (*func)(struct ieee80211com *, void *), void *arg) +{ + struct ieee80211com *ic; + + mtx_lock(&ieee80211_vap_mtx); + SLIST_FOREACH(ic, &ieee80211_list, ic_next) + func(ic, arg); + mtx_unlock(&ieee80211_vap_mtx); +} + /* * Default reset method for use with the ioctl support. This * method is invoked after any state change in the 802.11 @@ -261,11 +272,11 @@ ieee80211_ifattach(struct ieee80211com * ieee80211_power_attach(ic); ieee80211_proto_attach(ic); ieee80211_ht_attach(ic); - ieee80211_scan_attach(ic); ieee80211_add_vap(ic); - ieee80211_sysctl_attach(ic); /* NB: requires ic_vap */ + ieee80211_sysctl_attach(ic); /* NB: requires ic_vap */ + ieee80211_scan_attach(ic); /* NB: requires ic_sysctl_oid */ /* * Install a default reset method for the ioctl support. @@ -285,8 +296,8 @@ ieee80211_ifdetach(struct ieee80211com * ieee80211_remove_vap(ic); - ieee80211_sysctl_detach(ic); ieee80211_scan_detach(ic); + ieee80211_sysctl_detach(ic); ieee80211_ht_detach(ic); /* NB: must be called before ieee80211_node_detach */ ieee80211_proto_detach(ic); ==== //depot/projects/wifi/sys/net80211/ieee80211_freebsd.c#29 - /opt/sam_wifi/sys/net80211/ieee80211_freebsd.c ==== --- /tmp/tmp.775.90 2007-07-15 22:07:45.000000000 +0800 +++ /opt/sam_wifi/sys/net80211/ieee80211_freebsd.c 2007-07-15 17:13:55.000000000 +0800 @@ -128,6 +128,7 @@ ieee80211_sysctl_attach(struct ieee80211 "bmiss_max", CTLFLAG_RW, &ic->ic_bmiss_max, 0, "consecutive beacon misses before scanning"); ic->ic_sysctl = ctx; + ic->ic_sysctl_oid = oid; } void @@ -138,6 +139,7 @@ ieee80211_sysctl_detach(struct ieee80211 sysctl_ctx_free(ic->ic_sysctl); FREE(ic->ic_sysctl, M_DEVBUF); ic->ic_sysctl = NULL; + ic->ic_sysctl_oid = NULL; } } ==== //depot/projects/wifi/sys/net80211/ieee80211_scan.c#18 - /opt/sam_wifi/sys/net80211/ieee80211_scan.c ==== --- /tmp/tmp.775.102 2007-07-15 22:07:45.000000000 +0800 +++ /opt/sam_wifi/sys/net80211/ieee80211_scan.c 2007-07-15 21:58:30.000000000 +0800 @@ -85,6 +85,9 @@ static void scan_restart_pwrsav(void *); static void scan_curchan(struct ieee80211com *, unsigned long); static void scan_mindwell(struct ieee80211com *); static void scan_next(void *); +static void scan_sysctl_attach(struct ieee80211_scan_state *, + struct ieee80211com *); +static void scan_sysctl_detach(struct ieee80211_scan_state *); MALLOC_DEFINE(M_80211_SCAN, "80211scan", "802.11 scan state"); @@ -116,6 +119,8 @@ ieee80211_scan_attach(struct ieee80211co ic->ic_roam.rate11a = ROAM_RATE_11A_DEFAULT; ic->ic_roam.rate11b = ROAM_RATE_11B_DEFAULT; ic->ic_roam.rate11bOnly = ROAM_RATE_11BONLY_DEFAULT; + + scan_sysctl_attach(ic->ic_scan, ic); } void @@ -130,6 +135,7 @@ ieee80211_scan_detach(struct ieee80211co ss->ss_ops = NULL; } ic->ic_flags &= ~IEEE80211_F_SCAN; + scan_sysctl_detach(ss); ic->ic_scan = NULL; FREE(SCAN_PRIVATE(ss), M_80211_SCAN); } @@ -138,7 +144,6 @@ ieee80211_scan_detach(struct ieee80211co /* * Simple-minded scanner module support. */ -#define IEEE80211_SCANNER_MAX (IEEE80211_M_MONITOR+1) static const char *scan_modnames[IEEE80211_SCANNER_MAX] = { "wlan_scan_sta", /* IEEE80211_M_IBSS */ @@ -163,13 +168,44 @@ ieee80211_scanner_get(enum ieee80211_opm return scanners[mode]; } +struct scanner_sysctl_arg { + const struct ieee80211_scanner *scan; + enum ieee80211_opmode opmode; +}; + +static void +add_scanner_sysctl(struct ieee80211com *ic, void *xarg) +{ + struct scanner_sysctl_arg *arg = xarg; + + if (ic->ic_scan == NULL) + return; + arg->scan->scan_sysctl_attach(ic->ic_scan, ic, arg->opmode); +} + void ieee80211_scanner_register(enum ieee80211_opmode mode, const struct ieee80211_scanner *scan) { + struct scanner_sysctl_arg arg; + if (mode >= IEEE80211_SCANNER_MAX) return; scanners[mode] = scan; + + arg.scan = scan; + arg.opmode = mode; + ieee80211_iterate_vap(add_scanner_sysctl, &arg); +} + +static void +del_scanner_sysctl(struct ieee80211com *ic, void *xarg) +{ + struct scanner_sysctl_arg *arg = xarg; + + if (ic->ic_scan == NULL) + return; + arg->scan->scan_sysctl_detach(ic->ic_scan, arg->opmode); } void @@ -178,8 +214,15 @@ ieee80211_scanner_unregister(enum ieee80 { if (mode >= IEEE80211_SCANNER_MAX) return; - if (scanners[mode] == scan) + if (scanners[mode] == scan) { + struct scanner_sysctl_arg arg; + scanners[mode] = NULL; + + arg.scan = scan; + arg.opmode = mode; + ieee80211_iterate_vap(del_scanner_sysctl, &arg); + } } void @@ -187,9 +230,16 @@ ieee80211_scanner_unregister_all(const s { int m; - for (m = 0; m < IEEE80211_SCANNER_MAX; m++) - if (scanners[m] == scan) + for (m = 0; m < IEEE80211_SCANNER_MAX; m++) { + if (scanners[m] == scan) { + struct scanner_sysctl_arg arg; + scanners[m] = NULL; + arg.scan = scan; + arg.opmode = m; + ieee80211_iterate_vap(del_scanner_sysctl, &arg); + } + } } /* @@ -991,3 +1041,25 @@ ieee80211_scan_flush(struct ieee80211com ss->ss_ops->scan_flush(ss); } } + +static void +scan_sysctl_attach(struct ieee80211_scan_state *ss, struct ieee80211com *ic) +{ + int i; + + for (i = 0; i < IEEE80211_SCANNER_MAX; ++i) { + if (scanners[i] != NULL) + scanners[i]->scan_sysctl_attach(ss, ic, i); + } +} + +static void +scan_sysctl_detach(struct ieee80211_scan_state *ss) +{ + int i; + + for (i = 0; i < IEEE80211_SCANNER_MAX; ++i) { + if (scanners[i] != NULL) + scanners[i]->scan_sysctl_detach(ss, i); + } +} ==== //depot/projects/wifi/sys/net80211/ieee80211_scan.h#12 - /opt/sam_wifi/sys/net80211/ieee80211_scan.h ==== --- /tmp/tmp.775.123 2007-07-15 22:07:46.000000000 +0800 +++ /opt/sam_wifi/sys/net80211/ieee80211_scan.h 2007-07-15 19:26:11.000000000 +0800 @@ -28,6 +28,7 @@ #define _NET80211_IEEE80211_SCAN_H_ #define IEEE80211_SCAN_MAX IEEE80211_CHAN_MAX +#define IEEE80211_SCANNER_MAX (IEEE80211_M_MONITOR+1) struct ieee80211_scanner; @@ -57,6 +58,7 @@ struct ieee80211_scan_state { uint16_t ss_last; /* ix+1 of last chan to scan */ unsigned long ss_mindwell; /* min dwell on channel */ unsigned long ss_maxdwell; /* max dwell on channel */ + void *ss_sysctl[IEEE80211_SCANNER_MAX]; }; /* @@ -209,6 +211,10 @@ struct ieee80211_scanner { /* iterate over entries in the scan cache */ void (*scan_iterate)(struct ieee80211_scan_state *, ieee80211_scan_iter_func *, void *); + void (*scan_sysctl_attach)(struct ieee80211_scan_state *, + struct ieee80211com *, enum ieee80211_opmode); + void (*scan_sysctl_detach)(struct ieee80211_scan_state *, + enum ieee80211_opmode); }; void ieee80211_scanner_register(enum ieee80211_opmode, const struct ieee80211_scanner *); ==== //depot/projects/wifi/sys/net80211/ieee80211_scan_ap.c#9 - /opt/sam_wifi/sys/net80211/ieee80211_scan_ap.c ==== --- /tmp/tmp.775.146 2007-07-15 22:07:46.000000000 +0800 +++ /opt/sam_wifi/sys/net80211/ieee80211_scan_ap.c 2007-07-15 21:21:15.000000000 +0800 @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD: src/sys/net80211/iee #include #include #include +#include #include @@ -44,10 +45,19 @@ __FBSDID("$FreeBSD: src/sys/net80211/iee #include +#define AP_DWELL_MIN 200 /* msec */ +#define AP_DWELL_MAX 300 /* msec */ + struct ap_state { int as_maxrssi[IEEE80211_CHAN_MAX]; }; +struct ap_scan_sysctl { + struct sysctl_ctx_list ap_sysctl; + u_int ap_mindwell; + u_int ap_maxdwell; +}; + static int ap_flush(struct ieee80211_scan_state *); /* number of references from net80211 layer */ @@ -205,9 +215,19 @@ ap_start(struct ieee80211_scan_state *ss } } ss->ss_next = 0; - /* XXX tunables */ - ss->ss_mindwell = msecs_to_ticks(200); /* 200ms */ - ss->ss_maxdwell = msecs_to_ticks(300); /* 300ms */ + + KASSERT(ic->ic_opmode == IEEE80211_M_HOSTAP, + ("opmode(%u) is not HOSTAP\n", ic->ic_opmode)); + if (ss->ss_sysctl[ic->ic_opmode] != NULL) { + struct ap_scan_sysctl *ap_sysctl; + + ap_sysctl = ss->ss_sysctl[ic->ic_opmode]; + ss->ss_mindwell = msecs_to_ticks(ap_sysctl->ap_mindwell); + ss->ss_maxdwell = msecs_to_ticks(ap_sysctl->ap_maxdwell); + } else { + ss->ss_mindwell = msecs_to_ticks(AP_DWELL_MIN); + ss->ss_maxdwell = msecs_to_ticks(AP_DWELL_MAX); + } #ifdef IEEE80211_DEBUG if (ieee80211_msg_scan(ic)) { @@ -357,6 +377,67 @@ ap_assoc_fail(struct ieee80211_scan_stat /* should not be called */ } +static void +ap_sysctl_attach(struct ieee80211_scan_state *ss, struct ieee80211com *ic, + enum ieee80211_opmode opmode) +{ + struct ap_scan_sysctl *ap_sysctl; + struct sysctl_ctx_list *ctx; + struct sysctl_oid *oid; + + KASSERT(opmode == IEEE80211_M_HOSTAP, + ("opmode(%u) is not HOSTAP\n", opmode)); + KASSERT(ss->ss_sysctl[opmode] == NULL, + ("scannr sysctl is not empty\n")); + + if ((ic->ic_caps & IEEE80211_C_HOSTAP) == 0) + return; + + if (ic->ic_sysctl_oid == NULL) + return; + + ap_sysctl = malloc(sizeof(*ap_sysctl), M_80211_SCAN, + M_NOWAIT | M_ZERO); + if (ap_sysctl == NULL) { + if_printf(ic->ic_ifp, "allocate hostap_scan sysctl failed\n"); + return; + } + + ap_sysctl->ap_mindwell = AP_DWELL_MIN; + ap_sysctl->ap_maxdwell = AP_DWELL_MAX; + + ctx = &ap_sysctl->ap_sysctl; + sysctl_ctx_init(ctx); + oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(ic->ic_sysctl_oid), + OID_AUTO, "hostap_scan", CTLFLAG_RD, NULL, + "IEEE 80211 hostap-mode scan parameters"); + SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "mindwell", CTLFLAG_RW, &ap_sysctl->ap_mindwell, 0, + "min channel dwelling time (msec)"); + SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "maxdwell", CTLFLAG_RW, &ap_sysctl->ap_maxdwell, 0, + "max channel dwelling time (msec)"); + + ss->ss_sysctl[opmode] = ap_sysctl; +} + +static void +ap_sysctl_detach(struct ieee80211_scan_state *ss, enum ieee80211_opmode opmode) +{ + struct ap_scan_sysctl *ap_sysctl; + + KASSERT(opmode == IEEE80211_M_HOSTAP, + ("opmode(%u) is not HOSTAP\n", opmode)); + + ap_sysctl = ss->ss_sysctl[opmode]; + ss->ss_sysctl[opmode] = NULL; + + if (ap_sysctl != NULL) { + sysctl_ctx_free(&ap_sysctl->ap_sysctl); + free(ap_sysctl, M_80211_SCAN); + } +} + static const struct ieee80211_scanner ap_default = { .scan_name = "default", .scan_attach = ap_attach, @@ -371,6 +452,8 @@ static const struct ieee80211_scanner ap .scan_iterate = ap_iterate, .scan_assoc_success = ap_assoc_success, .scan_assoc_fail = ap_assoc_fail, + .scan_sysctl_attach = ap_sysctl_attach, + .scan_sysctl_detach = ap_sysctl_detach, }; /* ==== //depot/projects/wifi/sys/net80211/ieee80211_scan_sta.c#24 - /opt/sam_wifi/sys/net80211/ieee80211_scan_sta.c ==== --- /tmp/tmp.775.207 2007-07-15 22:07:47.000000000 +0800 +++ /opt/sam_wifi/sys/net80211/ieee80211_scan_sta.c 2007-07-15 21:29:02.000000000 +0800 @@ -30,9 +30,10 @@ __FBSDID("$FreeBSD: src/sys/net80211/iee * IEEE 802.11 station scanning support. */ #include -#include +#include #include #include +#include #include @@ -57,10 +58,15 @@ __FBSDID("$FreeBSD: src/sys/net80211/iee #define STA_FAILS_AGE (2*60) /* time before clearing fails (secs) */ #define STA_PURGE_SCANS 2 /* age for purging entries (scans) */ -/* XXX tunable */ #define STA_RSSI_MIN 8 /* min acceptable rssi */ #define STA_RSSI_MAX 40 /* max rssi for comparison */ +#define STA_DWELL_MIN 20 /* msec */ +#define STA_DWELL_MAX 200 /* msec */ + +#define IBSS_DWELL_MIN 200 /* msec */ +#define IBSS_DWELL_MAX 200 /* msec */ + #define RSSI_LPF_LEN 10 #define RSSI_EP_MULTIPLIER (1<<7) /* pow2 to optimize out * and / */ #define RSSI_IN(x) ((x) * RSSI_EP_MULTIPLIER) @@ -121,6 +127,14 @@ static void sta_flush_table(struct sta_t static int match_bss(struct ieee80211com *, const struct ieee80211_scan_state *, struct sta_entry *, int); +struct sta_scan_sysctl { + struct sysctl_ctx_list sta_sysctl; + u_int sta_mindwell; + u_int sta_maxdwell; + int sta_maxrssi; + int sta_minrssi; +}; + /* number of references from net80211 layer */ static int nrefs = 0; @@ -572,9 +586,19 @@ sta_start(struct ieee80211_scan_state *s } ss->ss_next = 0; - /* XXX tunables */ - ss->ss_mindwell = msecs_to_ticks(20); /* 20ms */ - ss->ss_maxdwell = msecs_to_ticks(200); /* 200ms */ + + KASSERT(ic->ic_opmode == IEEE80211_M_STA, + ("opmode(%u) is not STA\n", ic->ic_opmode)); + if (ss->ss_sysctl[ic->ic_opmode] != NULL) { + struct sta_scan_sysctl *sta_sysctl; + + sta_sysctl = ss->ss_sysctl[ic->ic_opmode]; + ss->ss_mindwell = msecs_to_ticks(sta_sysctl->sta_mindwell); + ss->ss_maxdwell = msecs_to_ticks(sta_sysctl->sta_maxdwell); + } else { + ss->ss_mindwell = msecs_to_ticks(STA_DWELL_MIN); + ss->ss_maxdwell = msecs_to_ticks(STA_DWELL_MAX); + } #ifdef IEEE80211_DEBUG if (ieee80211_msg_scan(ic)) { @@ -640,15 +664,17 @@ maxrate(const struct ieee80211_scan_entr * Used to select the best scan candidate for association in a BSS. */ static int -sta_compare(const struct sta_entry *a, const struct sta_entry *b) +sta_compare(const struct ieee80211_scan_state *ss, const struct sta_entry *a, + const struct sta_entry *b) { #define PREFER(_a,_b,_what) do { \ if (((_a) ^ (_b)) & (_what)) \ return ((_a) & (_what)) ? 1 : -1; \ } while (0) uint8_t maxa, maxb; - int8_t rssia, rssib; + int8_t rssia, rssib, maxrssi; int weight; + enum ieee80211_opmode opmode; /* privacy support */ PREFER(a->base.se_capinfo, b->base.se_capinfo, @@ -659,6 +685,16 @@ sta_compare(const struct sta_entry *a, c if (abs(weight) > 1) return weight; + opmode = ss->ss_ic->ic_opmode; + if (ss->ss_sysctl[opmode] != NULL) { + struct sta_scan_sysctl *sta_sysctl; + + sta_sysctl = ss->ss_sysctl[opmode]; + maxrssi = sta_sysctl->sta_maxrssi; + } else { + maxrssi = STA_RSSI_MAX; + } + /* * Compare rssi. If the two are considered equivalent * then fallback to other criteria. We threshold the @@ -667,8 +703,8 @@ sta_compare(const struct sta_entry *a, c * more desirable (e.g. an 11b-only ap with stronger * signal than an 11g ap). */ - rssia = MIN(a->base.se_rssi, STA_RSSI_MAX); - rssib = MIN(b->base.se_rssi, STA_RSSI_MAX); + rssia = MIN(a->base.se_rssi, maxrssi); + rssib = MIN(b->base.se_rssi, maxrssi); if (abs(rssib - rssia) < 5) { /* best/max rate preferred if signal level close enough XXX */ maxa = maxrate(&a->base); @@ -773,8 +809,18 @@ match_bss(struct ieee80211com *ic, { struct ieee80211_scan_entry *se = &se0->base; uint8_t rate; + int8_t minrssi; int fail; + if (ss->ss_sysctl[ic->ic_opmode] != NULL) { + struct sta_scan_sysctl *sta_sysctl; + + sta_sysctl = ss->ss_sysctl[ic->ic_opmode]; + minrssi = sta_sysctl->sta_minrssi; + } else { + minrssi = STA_RSSI_MIN; + } + fail = 0; if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, se->se_chan))) fail |= MATCH_CHANNEL; @@ -818,7 +864,7 @@ match_bss(struct ieee80211com *ic, /* NB: entries may be present awaiting purge, skip */ if (se0->se_notseen >= STA_PURGE_SCANS) fail |= MATCH_NOTSEEN; - if (se->se_rssi < STA_RSSI_MIN) + if (se->se_rssi < minrssi) fail |= MATCH_RSSI; #ifdef IEEE80211_DEBUG if (ieee80211_msg(ic, debug)) { @@ -896,7 +942,7 @@ select_bss(struct ieee80211_scan_state * if (match_bss(ic, ss, se, debug) == 0) { if (selbs == NULL) selbs = se; - else if (sta_compare(se, selbs) > 0) + else if (sta_compare(ss, se, selbs) > 0) selbs = se; } } @@ -1153,6 +1199,107 @@ sta_assoc_success(struct ieee80211_scan_ } } +static void +sta_sysctl_attach(struct ieee80211_scan_state *ss, struct ieee80211com *ic, + enum ieee80211_opmode opmode) +{ + struct sta_scan_sysctl *sta_sysctl; + struct sysctl_ctx_list *ctx; + struct sysctl_oid *oid; + const char *name, *desc; + unsigned long mindwell, maxdwell; + + KASSERT(opmode == IEEE80211_M_STA || + opmode == IEEE80211_M_IBSS || + opmode == IEEE80211_M_AHDEMO, + ("opmode(%u) is not STA/IBSS/AHDEMO\n", opmode)); + KASSERT(ss->ss_sysctl[opmode] == NULL, + ("scanner sysctl is not empty\n")); + + if (ic->ic_sysctl_oid == NULL) + return; + + name = desc = ""; + switch (opmode) { + case IEEE80211_M_STA: + mindwell = STA_DWELL_MIN; + maxdwell = STA_DWELL_MAX; + name = "sta_scan"; + desc = "IEEE 80211 sta-mode scan parameters"; + break; + case IEEE80211_M_IBSS: + if ((ic->ic_caps & IEEE80211_C_IBSS) == 0) + return; + mindwell = IBSS_DWELL_MIN; + maxdwell = IBSS_DWELL_MAX; + name = "ibss_scan"; + desc = "IEEE 80211 ibss-mode scan parameters"; + break; + case IEEE80211_M_AHDEMO: + if ((ic->ic_caps & IEEE80211_C_AHDEMO) == 0) + return; + mindwell = IBSS_DWELL_MIN; + maxdwell = IBSS_DWELL_MAX; + name = "ahdemo_scan"; + desc = "IEEE 80211 ahdemo-mode scan parameters"; + break; + default: + panic("%s: %s() unsupported opmode %d", ic->ic_ifp->if_xname, + __func__, opmode); + break; + } + + sta_sysctl = malloc(sizeof(*sta_sysctl), M_80211_SCAN, + M_NOWAIT | M_ZERO); + if (sta_sysctl == NULL) { + if_printf(ic->ic_ifp, "allocate %s sysctl failed\n", name); + return; + } + + sta_sysctl->sta_mindwell = mindwell; + sta_sysctl->sta_maxdwell = maxdwell; + sta_sysctl->sta_minrssi = STA_RSSI_MIN; + sta_sysctl->sta_maxrssi = STA_RSSI_MAX; + + ctx = &sta_sysctl->sta_sysctl; + sysctl_ctx_init(ctx); + oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(ic->ic_sysctl_oid), + OID_AUTO, name, CTLFLAG_RD, NULL, desc); + SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "mindwell", CTLFLAG_RW, &sta_sysctl->sta_mindwell, 0, + "min channel dwelling time (msec)"); + SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "maxdwell", CTLFLAG_RW, &sta_sysctl->sta_maxdwell, 0, + "max channel dwelling time (msec)"); + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "minrssi", CTLFLAG_RW, &sta_sysctl->sta_minrssi, 0, + "min acceptable rssi (.5 dBm)"); + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "maxrssi", CTLFLAG_RW, &sta_sysctl->sta_maxrssi, 0, + "max rssi for comparison (.5 dBm)"); + + ss->ss_sysctl[opmode] = sta_sysctl; +} + +static void +sta_sysctl_detach(struct ieee80211_scan_state *ss, enum ieee80211_opmode opmode) +{ + struct sta_scan_sysctl *sta_sysctl; + + KASSERT(opmode == IEEE80211_M_STA || + opmode == IEEE80211_M_IBSS || + opmode == IEEE80211_M_AHDEMO, + ("opmode(%u) is not STA/IBSS/AHDEMO\n", opmode)); + + sta_sysctl = ss->ss_sysctl[opmode]; + ss->ss_sysctl[opmode] = NULL; + + if (sta_sysctl != NULL) { + sysctl_ctx_free(&sta_sysctl->sta_sysctl); + free(sta_sysctl, M_80211_SCAN); + } +} + static const struct ieee80211_scanner sta_default = { .scan_name = "default", .scan_attach = sta_attach, @@ -1167,6 +1314,8 @@ static const struct ieee80211_scanner st .scan_iterate = sta_iterate, .scan_assoc_fail = sta_assoc_fail, .scan_assoc_success = sta_assoc_success, + .scan_sysctl_attach = sta_sysctl_attach, + .scan_sysctl_detach = sta_sysctl_detach, }; /* @@ -1248,9 +1397,20 @@ adhoc_start(struct ieee80211_scan_state add_channels(ic, ss, mode, scan->list, scan->count); } ss->ss_next = 0; - /* XXX tunables */ - ss->ss_mindwell = msecs_to_ticks(200); /* 200ms */ - ss->ss_maxdwell = msecs_to_ticks(200); /* 200ms */ + + KASSERT(ic->ic_opmode == IEEE80211_M_IBSS || + ic->ic_opmode == IEEE80211_M_AHDEMO, + ("opmode(%u) is not IBSS/AHDEMO\n", ic->ic_opmode)); + if (ss->ss_sysctl[ic->ic_opmode] != NULL) { + struct sta_scan_sysctl *sta_sysctl; + + sta_sysctl = ss->ss_sysctl[ic->ic_opmode]; + ss->ss_mindwell = msecs_to_ticks(sta_sysctl->sta_mindwell); + ss->ss_maxdwell = msecs_to_ticks(sta_sysctl->sta_maxdwell); + } else { + ss->ss_mindwell = msecs_to_ticks(IBSS_DWELL_MIN); + ss->ss_maxdwell = msecs_to_ticks(IBSS_DWELL_MAX); + } #ifdef IEEE80211_DEBUG if (ieee80211_msg_scan(ic)) { @@ -1405,6 +1565,8 @@ static const struct ieee80211_scanner ad .scan_iterate = sta_iterate, .scan_assoc_fail = sta_assoc_fail, .scan_assoc_success = sta_assoc_success, + .scan_sysctl_attach = sta_sysctl_attach, + .scan_sysctl_detach = sta_sysctl_detach, }; /* ==== //depot/projects/wifi/sys/net80211/ieee80211_var.h#60 - /opt/sam_wifi/sys/net80211/ieee80211_var.h ==== --- /tmp/tmp.775.276 2007-07-15 22:07:47.000000000 +0800 +++ /opt/sam_wifi/sys/net80211/ieee80211_var.h 2007-07-15 21:47:18.000000000 +0800 @@ -94,6 +94,7 @@ struct ieee80211com { ieee80211_com_lock_t ic_comlock; /* state update lock */ ieee80211_beacon_lock_t ic_beaconlock; /* beacon update lock */ struct ieee80211_stats ic_stats; /* statistics */ + struct sysctl_oid *ic_sysctl_oid; /* dynamic sysctl oid */ struct sysctl_ctx_list *ic_sysctl; /* dynamic sysctl context */ uint32_t ic_debug; /* debug msg flags */ int ic_vap; /* virtual AP index */ @@ -414,6 +415,8 @@ struct ieee80211_channel *ieee80211_find int freq, int flags); int ieee80211_setmode(struct ieee80211com *, enum ieee80211_phymode); enum ieee80211_phymode ieee80211_chan2mode(const struct ieee80211_channel *); +void ieee80211_iterate_vap(void (*func)(struct ieee80211com *, void *), + void *arg); /* * Key update synchronization methods. XXX should not be visible.