xref: /dflybsd-src/sys/netproto/802_11/wlan/ieee80211_ratectl.c (revision 744c01d0dc2aa1481a40e5b0988d15691602f5c9)
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.2 2006/12/22 23:57:53 swildner 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 
44 #include <netproto/802_11/ieee80211_var.h>
45 
46 static const struct ieee80211_ratectl *ratectls[IEEE80211_RATECTL_MAX] = {
47 	[IEEE80211_RATECTL_NONE]	= &ieee80211_ratectl_none
48 };
49 
50 static const char *ratectl_modname[IEEE80211_RATECTL_MAX] = {
51 	[IEEE80211_RATECTL_ONOE]	= "wlan_ratectl_onoe",
52 	[IEEE80211_RATECTL_AMRR]	= "wlan_ratectl_amrr"
53 };
54 
55 void
56 ieee80211_ratectl_attach(struct ieee80211com *ic)
57 {
58 	struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
59 	u_int cur_ratectl = rc_st->rc_st_ratectl;
60 
61 	rc_st->rc_st_ratectl_cap |= IEEE80211_RATECTL_CAP_NONE;
62 	rc_st->rc_st_ratectl = IEEE80211_RATECTL_NONE;
63 
64 	ieee80211_ratectl_change(ic, cur_ratectl);
65 }
66 
67 void
68 ieee80211_ratectl_detach(struct ieee80211com *ic)
69 {
70 	ieee80211_ratectl_change(ic, IEEE80211_RATECTL_NONE);
71 }
72 
73 void
74 ieee80211_ratectl_register(const struct ieee80211_ratectl *rc)
75 {
76 	/*
77 	 * Sanity checks
78 	 */
79 	if (rc->rc_ratectl >= IEEE80211_RATECTL_MAX) {
80 		kprintf("%s: rate control %s has an invalid index %d\n",
81 		       __func__, rc->rc_name, rc->rc_ratectl);
82 		return;
83 	}
84 	if (ratectls[rc->rc_ratectl] != NULL &&
85 	    ratectls[rc->rc_ratectl] != rc) {
86 		kprintf("%s: rate control index %d is registered by %s\n",
87 		       __func__, rc->rc_ratectl,
88 		       ratectls[rc->rc_ratectl]->rc_name);
89 		return;
90 	}
91 
92 	ratectls[rc->rc_ratectl] = rc;
93 }
94 
95 void
96 ieee80211_ratectl_unregister(const struct ieee80211_ratectl *rc)
97 {
98 	/*
99 	 * Sanity checks
100 	 */
101 	if (rc->rc_ratectl >= IEEE80211_RATECTL_MAX) {
102 		kprintf("%s: rate control %s has an invalid index %d\n",
103 		       __func__, rc->rc_name, rc->rc_ratectl);
104 		return;
105 	}
106 	if (ratectls[rc->rc_ratectl] != NULL &&
107 	    ratectls[rc->rc_ratectl] != rc) {
108 		kprintf("%s: rate control index %d is registered by %s\n",
109 		       __func__, rc->rc_ratectl,
110 		       ratectls[rc->rc_ratectl]->rc_name);
111 		return;
112 	}
113 
114 	/*
115 	 * Indiviual rate control module MUST maintain reference count itself.
116 	 */
117 	ratectls[rc->rc_ratectl] = NULL;
118 }
119 
120 int
121 ieee80211_ratectl_change(struct ieee80211com *ic, u_int rc_idx)
122 {
123 	struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
124 	const struct ieee80211_ratectl *rc, *rc_old;
125 
126 	if (rc_idx == rc_st->rc_st_ratectl) {
127 		/* Nothing need to be changed */
128 		return 0;
129 	}
130 
131 	if ((IEEE80211_RATECTL_CAP(rc_idx) & rc_st->rc_st_ratectl_cap) == 0) {
132 		/* We are not capable to do requested rate control */
133 		return EOPNOTSUPP;
134 	}
135 
136 	rc = ratectls[rc_idx];
137 	if (rc == NULL) {
138 		/* Try load the rate control module */
139 		ieee80211_load_module(ratectl_modname[rc_idx]);
140 
141 		/*
142 		 * If rate control module loaded it should immediately
143 		 * call ieee80211_ratectl_register() which will fill in
144 		 * the entry in the 'ratectls' array.
145 		 */
146 		rc = ratectls[rc_idx];
147 		if (rc == NULL) {
148 			kprintf("%s: can't load requested rate control module",
149 			       __func__);
150 			return EOPNOTSUPP;
151 		}
152 	}
153 
154 	/* Detach old rate control */
155 	rc_old = ratectls[rc_st->rc_st_ratectl];
156 	rc_old->rc_detach(rc_st->rc_st_ctx);
157 
158 	if (rc_st->rc_st_change != NULL)
159 		rc_st->rc_st_change(ic, rc_st->rc_st_ratectl, rc_idx);
160 
161 	/* Attach new rate control */
162 	rc_st->rc_st_ratectl = rc_idx;
163 	rc_st->rc_st_ctx = rc->rc_attach(ic);
164 
165 	return 0;
166 }
167 
168 void
169 ieee80211_ratectl_data_alloc(struct ieee80211_node *ni)
170 {
171 	struct ieee80211com *ic = ni->ni_ic;
172 	struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
173 	const struct ieee80211_ratectl *rc = ratectls[rc_st->rc_st_ratectl];
174 
175 	rc->rc_data_alloc(ni);
176 }
177 
178 void
179 ieee80211_ratectl_data_dup(const struct ieee80211_node *oni,
180 			   struct ieee80211_node *nni)
181 {
182 	struct ieee80211com *ic = oni->ni_ic;
183 	struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
184 	const struct ieee80211_ratectl *rc = ratectls[rc_st->rc_st_ratectl];
185 
186 	rc->rc_data_dup(oni, nni);
187 }
188 
189 void
190 ieee80211_ratectl_data_free(struct ieee80211_node *ni)
191 {
192 	struct ieee80211com *ic = ni->ni_ic;
193 	struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
194 	const struct ieee80211_ratectl *rc = ratectls[rc_st->rc_st_ratectl];
195 
196 	rc->rc_data_free(ni);
197 }
198 
199 void
200 ieee80211_ratectl_newstate(struct ieee80211com *ic, enum ieee80211_state state)
201 {
202 	struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
203 	const struct ieee80211_ratectl *rc = ratectls[rc_st->rc_st_ratectl];
204 
205 	rc->rc_newstate(rc_st->rc_st_ctx, state);
206 }
207 
208 void
209 ieee80211_ratectl_tx_complete(struct ieee80211_node *ni, int frame_len,
210 			      const struct ieee80211_ratectl_res res[],
211 			      int res_len, int short_retries, int long_retries,
212 			      int is_fail)
213 {
214 	struct ieee80211com *ic = ni->ni_ic;
215 	struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
216 	const struct ieee80211_ratectl *rc = ratectls[rc_st->rc_st_ratectl];
217 
218 	rc->rc_tx_complete(rc_st->rc_st_ctx, ni, frame_len, res, res_len,
219 			   long_retries, short_retries, is_fail);
220 }
221 
222 void
223 ieee80211_ratectl_newassoc(struct ieee80211_node *ni, int is_new)
224 {
225 	struct ieee80211com *ic = ni->ni_ic;
226 	struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
227 	const struct ieee80211_ratectl *rc = ratectls[rc_st->rc_st_ratectl];
228 
229 	rc->rc_newassoc(rc_st->rc_st_ctx, ni, is_new);
230 }
231 
232 int
233 ieee80211_ratectl_findrate(struct ieee80211_node *ni, int frame_len,
234 			   int rateidx[], int rateidx_len)
235 {
236 	struct ieee80211com *ic = ni->ni_ic;
237 	struct ieee80211_ratectl_state *rc_st = &ic->ic_ratectl;
238 	const struct ieee80211_ratectl *rc = ratectls[rc_st->rc_st_ratectl];
239 
240 	KKASSERT(rateidx_len > 0);
241 
242 	return rc->rc_findrate(rc_st->rc_st_ctx, ni, frame_len,
243 			       rateidx, rateidx_len);
244 }
245