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