[Madwifi-devel] [PATCH]NetBSD Ad-Hoc fiddling
Status: Beta
Brought to you by:
otaku
From: Jon A. <jon...@ro...> - 2004-09-12 04:32:48
|
I dunno if this actually useless, but I've been fiddling with Ad-Hoc mode...I checked NetBSD's CVS, and there was a handy page: http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/dev/ic/ath.c.diff?r1=1.35&r2=1.36&f=h I merged most of that...Badly. Long story short: I can make a reliable Ad-Hoc connection with Windows XP. Result of 5 minutes of testing: Before: Linux/Madwifi->Windows XP connection resulted in >50% packet loss. Now: 0% packet loss, and it doesn't disconnect randomly either. (This could be a fluke resulting from little testing though...) Patch below is against CVS of about 5-6 hours ago. It's also at http://www.janderson.ca/~janderson/madwifi-ibss.patch . There are too many problems to name, but it'd take me a week for me to fix 'em, so I figured I'd post it here as-is for now. Comments please, jon madwifi-ibss.patch: diff -urN madwifi.orig/ath/if_ath.c madwifi/ath/if_ath.c --- madwifi.orig/ath/if_ath.c 2004-09-10 11:17:26.000000000 -0400 +++ madwifi/ath/if_ath.c 2004-09-11 20:56:56.475641792 -0400 @@ -164,6 +164,9 @@ static void ath_rate_ctl_start(struct ath_softc *, struct ieee80211_node *); static void ath_rate_ctl_reset(struct ath_softc *, enum ieee80211_state); static void ath_rate_ctl(void *, struct ieee80211_node *); +static void ath_recv_mgmt(struct ieee80211com *, struct sk_buff *, + struct ieee80211_node *, int, int, u_int32_t); + #ifdef CONFIG_SYSCTL static void ath_dynamic_sysctl_register(struct ath_softc *); @@ -540,6 +543,8 @@ ic->ic_node_getrssi = ath_node_getrssi; sc->sc_newstate = ic->ic_newstate; ic->ic_newstate = ath_newstate; + sc->sc_recv_mgmt = ic->ic_recv_mgmt; + ic->ic_recv_mgmt = ath_recv_mgmt; ic->ic_crypto.cs_key_alloc = ath_key_alloc; ic->ic_crypto.cs_key_delete = ath_key_delete; ic->ic_crypto.cs_key_set = ath_key_set; @@ -1999,17 +2004,35 @@ sc->sc_imask |= HAL_INT_BMISS; ath_hal_intrset(ah, sc->sc_imask); } else { - DPRINTF(ATH_DEBUG_BEACON, "%s: intval %u nexttbtt %u\n", - __func__, ni->ni_intval, nexttbtt); ath_hal_intrset(ah, 0); - if (nexttbtt == ni->ni_intval) - intval |= HAL_BEACON_RESET_TSF; - if (ic->ic_opmode != IEEE80211_M_MONITOR) { - intval |= HAL_BEACON_ENA; - sc->sc_imask |= HAL_INT_SWBA; /* beacon prepare */ + sc->sc_imask |= HAL_INT_SWBA; /* beacon prepare */ + intval |= HAL_BEACON_ENA; + switch (ic->ic_opmode) { + /* No beacons in monitor, ad hoc-demo modes. */ + case IEEE80211_M_MONITOR: + case IEEE80211_M_AHDEMO: + intval &= ~HAL_BEACON_ENA; + /*FALLTHROUGH*/ + /* In IBSS mode, I am uncertain how SWBA interrupts + * work, so I just turn them off and use a self-linked + * descriptor. + */ + case IEEE80211_M_IBSS: + sc->sc_imask &= ~HAL_INT_SWBA; + nexttbtt = ni->ni_intval; + /*FALLTHROUGH*/ + case IEEE80211_M_HOSTAP: + default: + if (nexttbtt == ni->ni_intval) + intval |= HAL_BEACON_RESET_TSF; + break; } + DPRINTF(ATH_DEBUG_BEACON, "%s: intval %u nexttbtt %u\n", + __func__, ni->ni_intval, nexttbtt); ath_hal_beaconinit(ah, nexttbtt, intval); ath_hal_intrset(ah, sc->sc_imask); + if (ic->ic_opmode == IEEE80211_M_IBSS) + ath_beacon_tasklet(ic->ic_dev); } } @@ -3718,6 +3741,32 @@ return error; } +static void +ath_recv_mgmt(struct ieee80211com *ic, struct sk_buff *buf, + struct ieee80211_node *ni, int subtype, int rssi, u_int32_t rstamp) +{ + struct ath_softc *sc = (struct ath_softc*)ic->ic_dev->priv; + struct ath_hal *ah = sc->sc_ah; + + (*sc->sc_recv_mgmt)(ic, buf, ni, subtype, rssi, rstamp); + + switch (subtype) { + case IEEE80211_FC0_SUBTYPE_PROBE_RESP: + case IEEE80211_FC0_SUBTYPE_BEACON: + if (ic->ic_opmode != IEEE80211_M_IBSS || + ic->ic_state != IEEE80211_S_RUN) + break; + if (ieee80211_ibss_merge(ic, ni, ath_hal_gettsf64(ah)) == + ENETRESET) + ath_hal_setassocid(ah, ic->ic_bss->ni_bssid, 0); + break; + default: + break; + } + return; +} + + /* * Setup driver-specific state for a newly associated node. * Note that we're called also on a re-associate, the isnew diff -urN madwifi.orig/ath/if_athvar.h madwifi/ath/if_athvar.h --- madwifi.orig/ath/if_athvar.h 2004-09-10 11:17:26.000000000 -0400 +++ madwifi/ath/if_athvar.h 2004-09-11 20:41:38.048263976 -0400 @@ -201,6 +201,9 @@ void (*sc_node_copy)(struct ieee80211com *, struct ieee80211_node *, const struct ieee80211_node *); + void (*sc_recv_mgmt)(struct ieee80211com *, + struct sk_buff *, struct ieee80211_node *, + int, int, u_int32_t); struct ath_hal *sc_ah; /* Atheros HAL */ unsigned int sc_invalid : 1, /* being detached */ sc_mrretry : 1, /* multi-rate retry support */ diff -urN madwifi.orig/net80211/ieee80211_input.c madwifi/net80211/ieee80211_input.c --- madwifi.orig/net80211/ieee80211_input.c 2004-08-18 22:15:44.000000000 -0400 +++ madwifi/net80211/ieee80211_input.c 2004-09-11 21:36:36.257859904 -0400 @@ -2325,3 +2325,106 @@ /* XXX need different driver interface */ (*ic->ic_dev->hard_start_xmit)(skb, ic->ic_dev); } + +/*static int +do_slow_print(struct ieee80211com *ic, int *did_print) +{ + if ((ic->ic_if.if_flags & IFF_LINK0) == 0) + return 0; + if (!*did_print && (ic->ic_if.if_flags & IFF_DEBUG) == 0 && + !ratecheck(&ic->ic_last_merge_print, &ieee80211_merge_print_intvl)) + return 0; + + *did_print = 1; + return 1; +}*/ + +/* ieee80211_ibss_merge helps merge 802.11 ad hoc networks. The + * convention, set by the Wireless Ethernet Compatibility Alliance + * (WECA), is that an 802.11 station will change its BSSID to match + * the "oldest" 802.11 ad hoc network, on the same channel, that + * has the station's desired SSID. The "oldest" 802.11 network + * sends beacons with the greatest TSF timestamp. + * + * Return ENETRESET if the BSSID changed, 0 otherwise. + * + * XXX Perhaps we should compensate for the time that elapses + * between the MAC receiving the beacon and the host processing it + * in ieee80211_ibss_merge. + */ +int +ieee80211_ibss_merge(struct ieee80211com *ic, struct ieee80211_node *ni, + uint64_t local_tsft) +{ + uint64_t beacon_tsft; + int /*did_print = 0,*/ sign; + union { + uint64_t word; + uint8_t tstamp[8]; + } u; + + /* ensure alignment */ + (void)memcpy(&u, &ni->ni_tstamp[0], sizeof(u)); + beacon_tsft = le64_to_cpu(u.word); + // XXX is the above a correct translation for: beacon_tsft = le64toh(u.word); + + /* we are faster, let the other guy catch up */ + if (beacon_tsft < local_tsft) + sign = -1; + else + sign = 1; + + if (memcmp(ni->ni_bssid, ic->ic_bss->ni_bssid, + IEEE80211_ADDR_LEN) == 0) { + /* if (!do_slow_print(ic, &did_print)) + return 0; + printf("%s: tsft offset %s%" PRIu64 "\n", ic->ic_if.if_xname, + (sign < 0) ? "-" : "", + (sign < 0) + ? (local_tsft - beacon_tsft) + : (beacon_tsft - local_tsft)); */ + return 0; + } + + if (sign < 0) + return 0; + + if (ieee80211_match_bss(ic, ni) != 0) + return 0; + + /*if (do_slow_print(ic, &did_print)) { + printf("%s: atw_recv_beacon: bssid mismatch %s\n", + ic->ic_if.if_xname, ether_sprintf(ni->ni_bssid)); + printf("%s: my tsft %" PRIu64 " beacon tsft %" PRIu64 "\n", + ic->ic_if.if_xname, local_tsft, beacon_tsft); + printf("%s: sync TSF with %s\n", + ic->ic_if.if_xname, ether_sprintf(ni->ni_macaddr)); + }*/ + + ic->ic_flags &= ~IEEE80211_F_SIBSS; + + /* negotiate rates with new IBSS */ + ieee80211_fix_rate(ic, ni, IEEE80211_F_DOFRATE | + IEEE80211_F_DONEGO | IEEE80211_F_DODEL); + if (ni->ni_rates.rs_nrates == 0) { + /*if (do_slow_print(ic, &did_print)) { + printf("%s: rates mismatch, BSSID %s\n", + ic->ic_if.if_xname, ether_sprintf(ni->ni_bssid)); + }*/ + return 0; + } + + /*if (do_slow_print(ic, &did_print)) { + printf("%s: sync BSSID %s -> ", + ic->ic_if.if_xname, ether_sprintf(ic->ic_bss->ni_bssid)); + printf("%s ", ether_sprintf(ni->ni_bssid)); + printf("(from %s)\n", ether_sprintf(ni->ni_macaddr)); + }*/ + + /* FIXME-> How does madwifi do this? */ + // ieee80211_node_newstate(ni, IEEE80211_STA_BSS); + (*ic->ic_node_copy)(ic, ic->ic_bss, ni); + + return ENETRESET; +} + diff -urN madwifi.orig/net80211/ieee80211_node.c madwifi/net80211/ieee80211_node.c --- madwifi.orig/net80211/ieee80211_node.c 2004-08-18 22:09:13.000000000 -0400 +++ madwifi/net80211/ieee80211_node.c 2004-09-11 22:58:12.218560744 -0400 @@ -341,7 +341,8 @@ ieee80211_new_state(ic, IEEE80211_S_RUN, -1); } -static int +/* XXX NetBSD declares this static. */ +int ieee80211_match_bss(struct ieee80211com *ic, struct ieee80211_node *ni) { u_int8_t rate; @@ -404,6 +405,7 @@ #endif return fail; } +EXPORT_SYMBOL(ieee80211_ibss_merge); /* * Complete a scan of potential channels. diff -urN madwifi.orig/net80211/ieee80211_node.h madwifi/net80211/ieee80211_node.h --- madwifi.orig/net80211/ieee80211_node.h 2004-08-18 21:06:58.000000000 -0400 +++ madwifi/net80211/ieee80211_node.h 2004-09-11 22:56:08.990294288 -0400 @@ -213,4 +213,6 @@ extern void ieee80211_node_leave(struct ieee80211com *, struct ieee80211_node *); extern void ieee80211_set_shortslottime(struct ieee80211com *, int onoff); +/* XXX This was originally declared static. I'm just dumb, so I can't make it compile without warnings as such. */ +extern int ieee80211_match_bss(struct ieee80211com *ic, struct ieee80211_node *ni); #endif /* _NET80211_IEEE80211_NODE_H_ */ diff -urN madwifi.orig/net80211/ieee80211_proto.h madwifi/net80211/ieee80211_proto.h --- madwifi.orig/net80211/ieee80211_proto.h 2004-08-05 13:34:54.000000000 -0400 +++ madwifi/net80211/ieee80211_proto.h 2004-09-11 22:35:55.276806784 -0400 @@ -173,6 +173,8 @@ (((_ic)->ic_newstate)((_ic), (_nstate), (_arg))) extern void ieee80211_print_essid(const u_int8_t *, int); extern void ieee80211_dump_pkt(const u_int8_t *, int, int, int); +extern int ieee80211_ibss_merge(struct ieee80211com *, + struct ieee80211_node *, uint64_t); extern const char *ieee80211_state_name[IEEE80211_S_MAX]; |