From: Sascha Wildner Date: Sat, 22 Mar 2014 17:44:28 +0000 (+0100) Subject: kernel/802_11: Fix panic when the desired ratectl algorithm is unavailable. X-Git-Tag: v3.9.0~264 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/168783520f968823dd6e673c8c56ab86228b1bd9 kernel/802_11: Fix panic when the desired ratectl algorithm is unavailable. Set the default to NONE. When a driver calls ieee80211_ratectl_init(), try to use AMRR etc. if NONE is selected. Drivers may still select other algorithms using ieee80211_ratectl_set() prior to calling _init(). Due to our broken ieee80211_load_module(), we do not currently autoload the desired ratectl algorithm like FreeBSD does. Instead, a message about manually loading the module will be printed (see ieee80211_dragonfly.c). Reported-by: profmakx Taken-from: FreeBSD --- diff --git a/sys/conf/files b/sys/conf/files index 2e8eadd4d5..660c858a7c 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1232,6 +1232,7 @@ netproto/802_11/wlan/ieee80211_power.c optional wlan netproto/802_11/wlan/ieee80211_proto.c optional wlan netproto/802_11/wlan/ieee80211_radiotap.c optional wlan netproto/802_11/wlan/ieee80211_ratectl.c optional wlan +netproto/802_11/wlan/ieee80211_ratectl_none.c optional wlan netproto/802_11/wlan/ieee80211_regdomain.c optional wlan netproto/802_11/wlan/ieee80211_rssadapt.c optional wlan_rssadapt netproto/802_11/wlan/ieee80211_scan.c optional wlan diff --git a/sys/netproto/802_11/ieee80211_ratectl.h b/sys/netproto/802_11/ieee80211_ratectl.h index b652e80c98..37e80e4d32 100644 --- a/sys/netproto/802_11/ieee80211_ratectl.h +++ b/sys/netproto/802_11/ieee80211_ratectl.h @@ -22,14 +22,15 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: head/sys/net80211/ieee80211_ratectl.h 206398 2010-04-08 13:34:08Z rpaulo $ + * $FreeBSD: head/sys/net80211/ieee80211_ratectl.h 215289 2010-11-14 09:59:52Z bschmidt $ */ enum ieee80211_ratealgs { - IEEE80211_RATECTL_AMRR = 0, + IEEE80211_RATECTL_AMRR = 0, IEEE80211_RATECTL_RSSADAPT = 1, IEEE80211_RATECTL_ONOE = 2, IEEE80211_RATECTL_SAMPLE = 3, + IEEE80211_RATECTL_NONE = 4, IEEE80211_RATECTL_MAX }; @@ -56,16 +57,11 @@ struct ieee80211_ratectl { void ieee80211_ratectl_register(int, const struct ieee80211_ratectl *); void ieee80211_ratectl_unregister(int); +void ieee80211_ratectl_init(struct ieee80211vap *); void ieee80211_ratectl_set(struct ieee80211vap *, int); MALLOC_DECLARE(M_80211_RATECTL); -static __inline void -ieee80211_ratectl_init(struct ieee80211vap *vap) -{ - vap->iv_rate->ir_init(vap); -} - static __inline void ieee80211_ratectl_deinit(struct ieee80211vap *vap) { @@ -85,8 +81,6 @@ ieee80211_ratectl_node_deinit(struct ieee80211_node *ni) { const struct ieee80211vap *vap = ni->ni_vap; - if (ni->ni_rctls == NULL) /* ratectl not setup */ - return; vap->iv_rate->ir_node_deinit(ni); } @@ -95,8 +89,6 @@ ieee80211_ratectl_rate(struct ieee80211_node *ni, void *arg, uint32_t iarg) { const struct ieee80211vap *vap = ni->ni_vap; - if (ni->ni_rctls == NULL) /* ratectl not setup */ - return 0; return vap->iv_rate->ir_rate(ni, arg, iarg); } @@ -104,8 +96,6 @@ static __inline void ieee80211_ratectl_tx_complete(const struct ieee80211vap *vap, const struct ieee80211_node *ni, int status, void *arg1, void *arg2) { - if (ni->ni_rctls == NULL) /* ratectl not setup */ - return; vap->iv_rate->ir_tx_complete(vap, ni, status, arg1, arg2); } @@ -115,8 +105,6 @@ ieee80211_ratectl_tx_update(const struct ieee80211vap *vap, { if (vap->iv_rate->ir_tx_update == NULL) return; - if (ni->ni_rctls == NULL) /* ratectl not setup */ - return; vap->iv_rate->ir_tx_update(vap, ni, arg1, arg2, arg3); } diff --git a/sys/netproto/802_11/wlan/Makefile b/sys/netproto/802_11/wlan/Makefile index e71893de11..4d2ea3932e 100644 --- a/sys/netproto/802_11/wlan/Makefile +++ b/sys/netproto/802_11/wlan/Makefile @@ -1,5 +1,3 @@ -# $DragonFly: src/sys/netproto/802_11/wlan/Makefile,v 1.6 2006/09/01 15:12:11 sephe Exp $ - KMOD = wlan SRCS = ieee80211.c ieee80211_action.c ieee80211_adhoc.c ieee80211_ageq.c #SRCS += ieee80211_amrr.c @@ -9,7 +7,7 @@ SRCS += ieee80211_ht.c ieee80211_hwmp.c ieee80211_input.c ieee80211_ioctl.c SRCS += ieee80211_mesh.c ieee80211_monitor.c ieee80211_node.c SRCS += ieee80211_output.c ieee80211_phy.c ieee80211_power.c SRCS += ieee80211_proto.c ieee80211_radiotap.c -SRCS += ieee80211_ratectl.c +SRCS += ieee80211_ratectl.c ieee80211_ratectl_none.c SRCS += ieee80211_regdomain.c ieee80211_rssadapt.c SRCS += ieee80211_scan.c ieee80211_scan_sta.c ieee80211_sta.c SRCS += ieee80211_superg.c ieee80211_tdma.c ieee80211_wds.c diff --git a/sys/netproto/802_11/wlan/ieee80211_ratectl.c b/sys/netproto/802_11/wlan/ieee80211_ratectl.c index e66aabc5e7..cea3e59322 100644 --- a/sys/netproto/802_11/wlan/ieee80211_ratectl.c +++ b/sys/netproto/802_11/wlan/ieee80211_ratectl.c @@ -22,7 +22,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: head/sys/net80211/ieee80211_ratectl.c 206358 2010-04-07 15:29:13Z rpaulo $ + * $FreeBSD: head/sys/net80211/ieee80211_ratectl.c 214894 2010-11-06 18:17:20Z bschmidt $ */ #include @@ -38,6 +38,14 @@ static const struct ieee80211_ratectl *ratectls[IEEE80211_RATECTL_MAX]; +static const char *ratectl_modnames[IEEE80211_RATECTL_MAX] = { + [IEEE80211_RATECTL_AMRR] = "wlan_amrr", + [IEEE80211_RATECTL_RSSADAPT] = "wlan_rssadapt", + [IEEE80211_RATECTL_ONOE] = "wlan_onoe", + [IEEE80211_RATECTL_SAMPLE] = "wlan_sample", + [IEEE80211_RATECTL_NONE] = "wlan_none", +}; + MALLOC_DEFINE(M_80211_RATECTL, "80211ratectl", "802.11 rate control"); void @@ -56,10 +64,28 @@ ieee80211_ratectl_unregister(int type) ratectls[type] = NULL; } +void +ieee80211_ratectl_init(struct ieee80211vap *vap) +{ + if (vap->iv_rate == ratectls[IEEE80211_RATECTL_NONE]) + ieee80211_ratectl_set(vap, IEEE80211_RATECTL_AMRR); + vap->iv_rate->ir_init(vap); +} + void ieee80211_ratectl_set(struct ieee80211vap *vap, int type) { if (type >= IEEE80211_RATECTL_MAX) return; + if (ratectls[type] == NULL) { + ieee80211_load_module(ratectl_modnames[type]); + if (ratectls[type] == NULL) { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_RATECTL, + "%s: unable to load algo %u, module %s\n", + __func__, type, ratectl_modnames[type]); + vap->iv_rate = ratectls[IEEE80211_RATECTL_NONE]; + return; + } + } vap->iv_rate = ratectls[type]; } diff --git a/sys/netproto/802_11/wlan/ieee80211_ratectl_none.c b/sys/netproto/802_11/wlan/ieee80211_ratectl_none.c index 6b2a59127b..0b745d9929 100644 --- a/sys/netproto/802_11/wlan/ieee80211_ratectl_none.c +++ b/sys/netproto/802_11/wlan/ieee80211_ratectl_none.c @@ -1,129 +1,116 @@ -/* - * Copyright (c) 2006 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * +/*- + * Copyright (c) 2010 Bernhard Schmidt + * All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $DragonFly: src/sys/netproto/802_11/wlan/ieee80211_ratectl_none.c,v 1.3 2008/01/15 09:01:13 sephe Exp $ + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: head/sys/net80211/ieee80211_ratectl_none.c 257179 2013-10-26 18:18:50Z glebius $ */ +#include "opt_wlan.h" + #include +#include #include - +#include +#include +#include +#include + #include #include -#include - -#include +#include -static void *none_ratectl_attach(struct ieee80211vap *); -static void none_ratectl_detach(void *); -static void none_ratectl_init(struct ieee80211vap *); -static void none_ratectl_deinit(struct ieee80211vap *); -static void none_ratectl_node_init(struct ieee80211_node *); -static void none_ratectl_node_deinit(struct ieee80211_node *); -static void none_ratectl_rate(struct ieee80211vap *, void *, uint32_t); -static void none_ratectl_tx_complete(const struct ieee80211vap *, - struct ieee80211_node *, int, void *, void *); -static void none_ratectl_tx_update(const struct ieee80211vap *, - const struct ieee80211_node *, void *, void *, void *); -static void none_ratectl_setinterval(const struct ieee80211vap *, int); - -const struct ieee80211_ratectl ieee80211_ratectl_none = { - .rc_name = "none", - .rc_attach = none_ratectl_attach, - .rc_detach = none_ratectl_detach, - .rc_init = none_ratectl_init, - .rc_deinit = none_ratectl_deinit, - .rc_node_init = none_ratectl_node_init, - .rc_node_deinit = none_ratectl_node_deinit, - .rc_rate = none_ratectl_rate, - .rc_tx_complete = none_ratectl_tx_complete, - .rc_tx_update = none_ratectl_tx_update, - .rc_setinterval = none_ratectl_setinterval, -}; +#ifdef INET +#include +#include +#endif -IEEE80211_RATECTL_MODULE(ieee80211_ratectl_none, 1); -IEEE80211_RATECTL_ALG(ieee80211_ratectl_none, IEEE80211_RATECTL_NONE, - ieee80211_ratectl_none); +#include +#include static void -none_ratectl_setinterval(const struct ieee80211vap *vap __unused, - int msecs __unused) +none_init(struct ieee80211vap *vap) { } -static void * -none_ratectl_attach(struct ieee80211vap *vap) -{ - struct ieee80211_ratectl_state *rc_st = &vap->iv_ratectl; - - rc_st->rc_st_attach(vap, IEEE80211_RATECTL_NONE); - return NULL; -} - static void -none_ratectl_detach(void *arg __unused) +none_deinit(struct ieee80211vap *vap) { + kfree(vap->iv_rs, M_80211_RATECTL); } static void -none_ratectl_init(struct ieee80211vap *vap __unused) +none_node_init(struct ieee80211_node *ni) { + ni->ni_txrate = ni->ni_rates.rs_rates[0] & IEEE80211_RATE_VAL; } static void -none_ratectl_deinit(struct ieee80211vap *vap __unused) +none_node_deinit(struct ieee80211_node *ni) { } -static void -none_ratectl_node_init(struct ieee80211_node *ni __unused) +static int +none_rate(struct ieee80211_node *ni, void *arg __unused, uint32_t iarg __unused) { + int rix = 0; + + ni->ni_txrate = ni->ni_rates.rs_rates[rix] & IEEE80211_RATE_VAL; + return rix; } static void -none_ratectl_node_deinit(struct ieee80211_node *ni __unused) +none_tx_complete(const struct ieee80211vap *vap, + const struct ieee80211_node *ni, int ok, + void *arg1, void *arg2 __unused) { } static void -none_ratectl_tx_complete(const struct ieee80211vap *vap __unused, - struct ieee80211_node *ni __unused, int ok __unused, - void *arg1 __unused, void *arg2 __unused) +none_tx_update(const struct ieee80211vap *vap, const struct ieee80211_node *ni, + void *arg1, void *arg2, void *arg3) { } static void -none_ratectl_tx_update(const struct ieee80211vap *vap __unused, - const struct ieee80211_node *ni __unused, - void *arg1 __unused, void *arg2 __unused, void *arg3 __unused) +none_setinterval(const struct ieee80211vap *vap, int msecs) { } + +/* number of references from net80211 layer */ +static int nrefs = 0; + +static const struct ieee80211_ratectl none = { + .ir_name = "none", + .ir_attach = NULL, + .ir_detach = NULL, + .ir_init = none_init, + .ir_deinit = none_deinit, + .ir_node_init = none_node_init, + .ir_node_deinit = none_node_deinit, + .ir_rate = none_rate, + .ir_tx_complete = none_tx_complete, + .ir_tx_update = none_tx_update, + .ir_setinterval = none_setinterval, +}; +IEEE80211_RATECTL_MODULE(ratectl_none, 1); +IEEE80211_RATECTL_ALG(none, IEEE80211_RATECTL_NONE, none);