Merge branch 'master' into net80211-update
[dragonfly.git] / sys / netproto / 802_11 / wlan / ieee80211_ratectl.c
1 /*
2  * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
3  * 
4  * This code is derived from software contributed to The DragonFly Project
5  * by Sepherosa Ziehau <sepherosa@gmail.com>
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  * 
34  * $DragonFly: src/sys/netproto/802_11/wlan/ieee80211_ratectl.c,v 1.5 2008/01/15 09:01:13 sephe Exp $
35  */
36
37 #include <sys/param.h>
38 #include <sys/kernel.h>
39  
40 #include <net/if.h>
41 #include <net/if_media.h>
42 #include <net/if_arp.h>
43 #include <net/route.h>
44
45 #include <netproto/802_11/ieee80211_var.h>
46
47 static const struct ieee80211_ratectl *ratectls[IEEE80211_RATECTL_MAX] = {
48         [IEEE80211_RATECTL_NONE]        = &ieee80211_ratectl_none
49 };
50
51 static const char *ratectl_modname[IEEE80211_RATECTL_MAX] = {
52         [IEEE80211_RATECTL_ONOE]        = "wlan_ratectl_onoe",
53         [IEEE80211_RATECTL_AMRR]        = "wlan_ratectl_amrr",
54         [IEEE80211_RATECTL_SAMPLE]      = "wlan_ratectl_sample"
55 };
56
57 void
58 ieee80211_ratectl_attach(struct ieee80211com *ic)
59 {
60         struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
61         u_int cur_ratectl = rc_st->rc_st_ratectl;
62
63         rc_st->rc_st_ratectl_cap |= IEEE80211_RATECTL_CAP_NONE;
64         rc_st->rc_st_ratectl = IEEE80211_RATECTL_NONE;
65
66         ieee80211_ratectl_change(ic, cur_ratectl);
67 }
68
69 void
70 ieee80211_ratectl_detach(struct ieee80211com *ic)
71 {
72         ieee80211_ratectl_change(ic, IEEE80211_RATECTL_NONE);
73 }
74
75 void
76 ieee80211_ratectl_register(const struct ieee80211_ratectl *rc)
77 {
78         /*
79          * Sanity checks
80          */
81         if (rc->rc_ratectl >= IEEE80211_RATECTL_MAX) {
82                 kprintf("%s: rate control %s has an invalid index %d\n",
83                        __func__, rc->rc_name, rc->rc_ratectl);
84                 return;
85         }
86         if (ratectls[rc->rc_ratectl] != NULL &&
87             ratectls[rc->rc_ratectl] != rc) {
88                 kprintf("%s: rate control index %d is registered by %s\n",
89                        __func__, rc->rc_ratectl,
90                        ratectls[rc->rc_ratectl]->rc_name);
91                 return;
92         }
93
94         ratectls[rc->rc_ratectl] = rc;
95 }
96
97 void
98 ieee80211_ratectl_unregister(const struct ieee80211_ratectl *rc)
99 {
100         /*
101          * Sanity checks
102          */
103         if (rc->rc_ratectl >= IEEE80211_RATECTL_MAX) {
104                 kprintf("%s: rate control %s has an invalid index %d\n",
105                        __func__, rc->rc_name, rc->rc_ratectl);
106                 return;
107         }
108         if (ratectls[rc->rc_ratectl] != NULL &&
109             ratectls[rc->rc_ratectl] != rc) {
110                 kprintf("%s: rate control index %d is registered by %s\n",
111                        __func__, rc->rc_ratectl,
112                        ratectls[rc->rc_ratectl]->rc_name);
113                 return;
114         }
115
116         /*
117          * Indiviual rate control module MUST maintain reference count itself.
118          */
119         ratectls[rc->rc_ratectl] = NULL;
120 }
121
122 int
123 ieee80211_ratectl_change(struct ieee80211com *ic, u_int rc_idx)
124 {
125         struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
126         const struct ieee80211_ratectl *rc, *rc_old;
127
128         if (rc_idx == rc_st->rc_st_ratectl) {
129                 /* Nothing need to be changed */
130                 return 0;
131         }
132
133         if ((IEEE80211_RATECTL_CAP(rc_idx) & rc_st->rc_st_ratectl_cap) == 0) {
134                 /* We are not capable to do requested rate control */
135                 return EOPNOTSUPP;
136         }
137
138         rc = ratectls[rc_idx];
139         if (rc == NULL) {
140                 /* Try load the rate control module */
141                 ieee80211_load_module(ratectl_modname[rc_idx]);
142
143                 /*
144                  * If rate control module loaded it should immediately
145                  * call ieee80211_ratectl_register() which will fill in
146                  * the entry in the 'ratectls' array.
147                  */
148                 rc = ratectls[rc_idx];
149                 if (rc == NULL) {
150                         kprintf("%s: can't load requested rate control module",
151                                __func__);
152                         return EOPNOTSUPP;
153                 }
154         }
155
156         /* Detach old rate control */
157         rc_old = ratectls[rc_st->rc_st_ratectl];
158         rc_old->rc_detach(rc_st->rc_st_ctx);
159
160         /* Attach new rate control */
161         rc_st->rc_st_ratectl = rc_idx;
162         rc_st->rc_st_ctx = rc->rc_attach(ic);
163
164         return 0;
165 }
166
167 void
168 ieee80211_ratectl_data_alloc(struct ieee80211_node *ni)
169 {
170         struct ieee80211com *ic = ni->ni_ic;
171         struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
172         const struct ieee80211_ratectl *rc = ratectls[rc_st->rc_st_ratectl];
173
174         rc->rc_data_alloc(ni);
175 }
176
177 void
178 ieee80211_ratectl_data_dup(const struct ieee80211_node *oni,
179                            struct ieee80211_node *nni)
180 {
181         struct ieee80211com *ic = oni->ni_ic;
182         struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
183         const struct ieee80211_ratectl *rc = ratectls[rc_st->rc_st_ratectl];
184
185         rc->rc_data_dup(oni, nni);
186 }
187
188 void
189 ieee80211_ratectl_data_free(struct ieee80211_node *ni)
190 {
191         struct ieee80211com *ic = ni->ni_ic;
192         struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
193         const struct ieee80211_ratectl *rc = ratectls[rc_st->rc_st_ratectl];
194
195         rc->rc_data_free(ni);
196 }
197
198 void
199 ieee80211_ratectl_newstate(struct ieee80211com *ic, enum ieee80211_state state)
200 {
201         struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
202         const struct ieee80211_ratectl *rc = ratectls[rc_st->rc_st_ratectl];
203
204         rc->rc_newstate(rc_st->rc_st_ctx, state);
205 }
206
207 void
208 ieee80211_ratectl_tx_complete(struct ieee80211_node *ni, int frame_len,
209                               const struct ieee80211_ratectl_res res[],
210                               int res_len, int data_retries, int rts_retries,
211                               int is_fail)
212 {
213         struct ieee80211com *ic = ni->ni_ic;
214         struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
215         const struct ieee80211_ratectl *rc = ratectls[rc_st->rc_st_ratectl];
216
217         rc->rc_tx_complete(rc_st->rc_st_ctx, ni, frame_len, res, res_len,
218                            data_retries, rts_retries, is_fail);
219 }
220
221 void
222 ieee80211_ratectl_newassoc(struct ieee80211_node *ni, int is_new)
223 {
224         struct ieee80211com *ic = ni->ni_ic;
225         struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
226         const struct ieee80211_ratectl *rc = ratectls[rc_st->rc_st_ratectl];
227
228         rc->rc_newassoc(rc_st->rc_st_ctx, ni, is_new);
229 }
230
231 int
232 ieee80211_ratectl_findrate(struct ieee80211_node *ni, int frame_len,
233                            int rateidx[], int rateidx_len)
234 {
235         struct ieee80211com *ic = ni->ni_ic;
236         struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
237         const struct ieee80211_ratectl *rc = ratectls[rc_st->rc_st_ratectl];
238
239         KKASSERT(rateidx_len > 0);
240
241         return rc->rc_findrate(rc_st->rc_st_ctx, ni, frame_len,
242                                rateidx, rateidx_len);
243 }