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