kernel/802_11: Fix panic when the desired ratectl algorithm is unavailable.
authorSascha Wildner <saw@online.de>
Sat, 22 Mar 2014 17:44:28 +0000 (18:44 +0100)
committerSascha Wildner <saw@online.de>
Sat, 22 Mar 2014 19:17:23 +0000 (20:17 +0100)
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

sys/conf/files
sys/netproto/802_11/ieee80211_ratectl.h
sys/netproto/802_11/wlan/Makefile
sys/netproto/802_11/wlan/ieee80211_ratectl.c
sys/netproto/802_11/wlan/ieee80211_ratectl_none.c

index 2e8eadd..660c858 100644 (file)
@@ -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
index b652e80..37e80e4 100644 (file)
  * (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);
 }
 
index e71893d..4d2ea39 100644 (file)
@@ -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
index e66aabc..cea3e59 100644 (file)
@@ -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 <sys/param.h>
 
 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];
 }
index 6b2a591..0b745d9 100644 (file)
-/*
- * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
- * 
- * This code is derived from software contributed to The DragonFly Project
- * by Sepherosa Ziehau <sepherosa@gmail.com>
- * 
+/*-
+ * Copyright (c) 2010 Bernhard Schmidt <bschmidt@FreeBSD.org>
+ * 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 <sys/param.h>
+#include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
 #include <net/if.h>
 #include <net/if_media.h>
-#include <net/if_arp.h>
-
-#include <netproto/802_11/ieee80211_var.h>
+#include <net/ethernet.h>
 
-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 <netinet/in.h>
+#include <netinet/if_ether.h>
+#endif
 
-IEEE80211_RATECTL_MODULE(ieee80211_ratectl_none, 1);
-IEEE80211_RATECTL_ALG(ieee80211_ratectl_none, IEEE80211_RATECTL_NONE,
-       ieee80211_ratectl_none);
+#include <netproto/802_11/ieee80211_var.h>
+#include <netproto/802_11/ieee80211_ratectl.h>
 
 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);