14028af95SRui Paulo /*-
24028af95SRui Paulo * Copyright (c) 2010 Rui Paulo <rpaulo@FreeBSD.org>
34028af95SRui Paulo * All rights reserved.
4b9334f94SSepherosa Ziehau *
5b9334f94SSepherosa Ziehau * Redistribution and use in source and binary forms, with or without
6b9334f94SSepherosa Ziehau * modification, are permitted provided that the following conditions
7b9334f94SSepherosa Ziehau * are met:
8b9334f94SSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright
9b9334f94SSepherosa Ziehau * notice, this list of conditions and the following disclaimer.
10b9334f94SSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright
114028af95SRui Paulo * notice, this list of conditions and the following disclaimer in the
124028af95SRui Paulo * documentation and/or other materials provided with the distribution.
13b9334f94SSepherosa Ziehau *
144028af95SRui Paulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
154028af95SRui Paulo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
164028af95SRui Paulo * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
174028af95SRui Paulo * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
184028af95SRui Paulo * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
194028af95SRui Paulo * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
204028af95SRui Paulo * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
214028af95SRui Paulo * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
224028af95SRui Paulo * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
234028af95SRui Paulo * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24b9334f94SSepherosa Ziehau */
25b9334f94SSepherosa Ziehau
26085ff963SMatthew Dillon #include <sys/cdefs.h>
27085ff963SMatthew Dillon __FBSDID("$FreeBSD$");
28085ff963SMatthew Dillon
29b9334f94SSepherosa Ziehau #include <sys/param.h>
30b9334f94SSepherosa Ziehau #include <sys/kernel.h>
314f655ef5SMatthew Dillon #include <sys/sbuf.h>
324028af95SRui Paulo #include <sys/systm.h>
334028af95SRui Paulo #include <sys/socket.h>
34085ff963SMatthew Dillon #include <sys/malloc.h>
35b9334f94SSepherosa Ziehau
36b9334f94SSepherosa Ziehau #include <net/if.h>
37*bff82488SAaron LI #include <net/if_var.h>
38b9334f94SSepherosa Ziehau #include <net/if_media.h>
39085ff963SMatthew Dillon #include <net/ethernet.h>
40085ff963SMatthew Dillon #include <net/route.h>
41b9334f94SSepherosa Ziehau
42b9334f94SSepherosa Ziehau #include <netproto/802_11/ieee80211_var.h>
434028af95SRui Paulo #include <netproto/802_11/ieee80211_ratectl.h>
44b9334f94SSepherosa Ziehau
454028af95SRui Paulo static const struct ieee80211_ratectl *ratectls[IEEE80211_RATECTL_MAX];
46b9334f94SSepherosa Ziehau
4716878352SSascha Wildner static const char *ratectl_modnames[IEEE80211_RATECTL_MAX] = {
4816878352SSascha Wildner [IEEE80211_RATECTL_AMRR] = "wlan_amrr",
4916878352SSascha Wildner [IEEE80211_RATECTL_RSSADAPT] = "wlan_rssadapt",
5016878352SSascha Wildner [IEEE80211_RATECTL_ONOE] = "wlan_onoe",
5116878352SSascha Wildner [IEEE80211_RATECTL_SAMPLE] = "wlan_sample",
5216878352SSascha Wildner [IEEE80211_RATECTL_NONE] = "wlan_none",
5316878352SSascha Wildner };
5416878352SSascha Wildner
554028af95SRui Paulo MALLOC_DEFINE(M_80211_RATECTL, "80211ratectl", "802.11 rate control");
56b9334f94SSepherosa Ziehau
57b9334f94SSepherosa Ziehau void
ieee80211_ratectl_register(int type,const struct ieee80211_ratectl * ratectl)584028af95SRui Paulo ieee80211_ratectl_register(int type, const struct ieee80211_ratectl *ratectl)
59b9334f94SSepherosa Ziehau {
604028af95SRui Paulo if (type >= IEEE80211_RATECTL_MAX)
61b9334f94SSepherosa Ziehau return;
624028af95SRui Paulo ratectls[type] = ratectl;
63b9334f94SSepherosa Ziehau }
644028af95SRui Paulo
654028af95SRui Paulo void
ieee80211_ratectl_unregister(int type)664028af95SRui Paulo ieee80211_ratectl_unregister(int type)
674028af95SRui Paulo {
684028af95SRui Paulo if (type >= IEEE80211_RATECTL_MAX)
69b9334f94SSepherosa Ziehau return;
704028af95SRui Paulo ratectls[type] = NULL;
71b9334f94SSepherosa Ziehau }
72b9334f94SSepherosa Ziehau
734f655ef5SMatthew Dillon static void
ieee80211_ratectl_sysctl_stats_node_iter(void * arg,struct ieee80211_node * ni)744f655ef5SMatthew Dillon ieee80211_ratectl_sysctl_stats_node_iter(void *arg, struct ieee80211_node *ni)
754f655ef5SMatthew Dillon {
764f655ef5SMatthew Dillon
774f655ef5SMatthew Dillon struct sbuf *sb = (struct sbuf *) arg;
784f655ef5SMatthew Dillon #if defined(__DragonFly__)
794f655ef5SMatthew Dillon sbuf_printf(sb, "MAC: %6s\n", ether_sprintf(ni->ni_macaddr));
804f655ef5SMatthew Dillon #else
814f655ef5SMatthew Dillon sbuf_printf(sb, "MAC: %6D\n", ni->ni_macaddr, ":");
824f655ef5SMatthew Dillon #endif
834f655ef5SMatthew Dillon ieee80211_ratectl_node_stats(ni, sb);
844f655ef5SMatthew Dillon sbuf_printf(sb, "\n");
854f655ef5SMatthew Dillon }
864f655ef5SMatthew Dillon
874f655ef5SMatthew Dillon static int
ieee80211_ratectl_sysctl_stats(SYSCTL_HANDLER_ARGS)884f655ef5SMatthew Dillon ieee80211_ratectl_sysctl_stats(SYSCTL_HANDLER_ARGS)
894f655ef5SMatthew Dillon {
904f655ef5SMatthew Dillon struct ieee80211vap *vap = arg1;
914f655ef5SMatthew Dillon struct ieee80211com *ic = vap->iv_ic;
924f655ef5SMatthew Dillon struct sbuf sb;
934f655ef5SMatthew Dillon int error;
944f655ef5SMatthew Dillon
954f655ef5SMatthew Dillon #if defined(__DragonFly__)
964f655ef5SMatthew Dillon #else
974f655ef5SMatthew Dillon error = sysctl_wire_old_buffer(req, 0);
984f655ef5SMatthew Dillon if (error)
994f655ef5SMatthew Dillon return (error);
1004f655ef5SMatthew Dillon #endif
1014f655ef5SMatthew Dillon sbuf_new_for_sysctl(&sb, NULL, 8, req);
1024f655ef5SMatthew Dillon #if defined(__DragonFly__)
1034f655ef5SMatthew Dillon #else
1044f655ef5SMatthew Dillon sbuf_clear_flags(&sb, SBUF_INCLUDENUL);
1054f655ef5SMatthew Dillon #endif
1064f655ef5SMatthew Dillon
1074f655ef5SMatthew Dillon IEEE80211_LOCK(ic);
1084f655ef5SMatthew Dillon ieee80211_iterate_nodes(&ic->ic_sta,
1094f655ef5SMatthew Dillon ieee80211_ratectl_sysctl_stats_node_iter,
1104f655ef5SMatthew Dillon &sb);
1114f655ef5SMatthew Dillon IEEE80211_UNLOCK(ic);
1124f655ef5SMatthew Dillon
1134f655ef5SMatthew Dillon error = sbuf_finish(&sb);
1144f655ef5SMatthew Dillon sbuf_delete(&sb);
1154f655ef5SMatthew Dillon return (error);
1164f655ef5SMatthew Dillon }
1174f655ef5SMatthew Dillon
118b9334f94SSepherosa Ziehau void
ieee80211_ratectl_init(struct ieee80211vap * vap)11916878352SSascha Wildner ieee80211_ratectl_init(struct ieee80211vap *vap)
12016878352SSascha Wildner {
12116878352SSascha Wildner if (vap->iv_rate == ratectls[IEEE80211_RATECTL_NONE])
12216878352SSascha Wildner ieee80211_ratectl_set(vap, IEEE80211_RATECTL_AMRR);
12316878352SSascha Wildner vap->iv_rate->ir_init(vap);
1244f655ef5SMatthew Dillon
1254f655ef5SMatthew Dillon /* Attach generic stats sysctl */
1264f655ef5SMatthew Dillon #if defined(__DragonFly__)
1274f655ef5SMatthew Dillon SYSCTL_ADD_PROC(vap->iv_sysctl, SYSCTL_CHILDREN(vap->iv_oid), OID_AUTO,
1284f655ef5SMatthew Dillon "rate_stats", CTLTYPE_STRING | CTLFLAG_RD, vap,
1294f655ef5SMatthew Dillon 0, ieee80211_ratectl_sysctl_stats, "A", "ratectl node stats");
1304f655ef5SMatthew Dillon #else
1314f655ef5SMatthew Dillon SYSCTL_ADD_PROC(vap->iv_sysctl, SYSCTL_CHILDREN(vap->iv_oid), OID_AUTO,
1324f655ef5SMatthew Dillon "rate_stats", CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, vap,
1334f655ef5SMatthew Dillon 0, ieee80211_ratectl_sysctl_stats, "A", "ratectl node stats");
1344f655ef5SMatthew Dillon #endif
13516878352SSascha Wildner }
13616878352SSascha Wildner
13716878352SSascha Wildner void
ieee80211_ratectl_set(struct ieee80211vap * vap,int type)1384028af95SRui Paulo ieee80211_ratectl_set(struct ieee80211vap *vap, int type)
139b9334f94SSepherosa Ziehau {
1404028af95SRui Paulo if (type >= IEEE80211_RATECTL_MAX)
141b9334f94SSepherosa Ziehau return;
14216878352SSascha Wildner if (ratectls[type] == NULL) {
14316878352SSascha Wildner ieee80211_load_module(ratectl_modnames[type]);
14416878352SSascha Wildner if (ratectls[type] == NULL) {
14516878352SSascha Wildner IEEE80211_DPRINTF(vap, IEEE80211_MSG_RATECTL,
14616878352SSascha Wildner "%s: unable to load algo %u, module %s\n",
14716878352SSascha Wildner __func__, type, ratectl_modnames[type]);
14816878352SSascha Wildner vap->iv_rate = ratectls[IEEE80211_RATECTL_NONE];
14916878352SSascha Wildner return;
15016878352SSascha Wildner }
15116878352SSascha Wildner }
1524028af95SRui Paulo vap->iv_rate = ratectls[type];
153b9334f94SSepherosa Ziehau }
154