Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.27-rc3 521 lines 13 kB view raw
1/* 2 * mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211 3 * Copyright (c) 2008, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 */ 9 10/* 11 * TODO: 12 * - IBSS mode simulation (Beacon transmission with competition for "air time") 13 * - IEEE 802.11a and 802.11n modes 14 * - RX filtering based on filter configuration (data->rx_filter) 15 */ 16 17#include <net/mac80211.h> 18#include <net/ieee80211_radiotap.h> 19#include <linux/if_arp.h> 20#include <linux/rtnetlink.h> 21#include <linux/etherdevice.h> 22 23MODULE_AUTHOR("Jouni Malinen"); 24MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211"); 25MODULE_LICENSE("GPL"); 26 27static int radios = 2; 28module_param(radios, int, 0444); 29MODULE_PARM_DESC(radios, "Number of simulated radios"); 30 31 32static struct class *hwsim_class; 33 34static struct ieee80211_hw **hwsim_radios; 35static int hwsim_radio_count; 36static struct net_device *hwsim_mon; /* global monitor netdev */ 37 38 39static const struct ieee80211_channel hwsim_channels[] = { 40 { .center_freq = 2412 }, 41 { .center_freq = 2417 }, 42 { .center_freq = 2422 }, 43 { .center_freq = 2427 }, 44 { .center_freq = 2432 }, 45 { .center_freq = 2437 }, 46 { .center_freq = 2442 }, 47 { .center_freq = 2447 }, 48 { .center_freq = 2452 }, 49 { .center_freq = 2457 }, 50 { .center_freq = 2462 }, 51 { .center_freq = 2467 }, 52 { .center_freq = 2472 }, 53 { .center_freq = 2484 }, 54}; 55 56static const struct ieee80211_rate hwsim_rates[] = { 57 { .bitrate = 10 }, 58 { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, 59 { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, 60 { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, 61 { .bitrate = 60 }, 62 { .bitrate = 90 }, 63 { .bitrate = 120 }, 64 { .bitrate = 180 }, 65 { .bitrate = 240 }, 66 { .bitrate = 360 }, 67 { .bitrate = 480 }, 68 { .bitrate = 540 } 69}; 70 71struct mac80211_hwsim_data { 72 struct device *dev; 73 struct ieee80211_supported_band band; 74 struct ieee80211_channel channels[ARRAY_SIZE(hwsim_channels)]; 75 struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; 76 77 struct ieee80211_channel *channel; 78 int radio_enabled; 79 unsigned long beacon_int; /* in jiffies unit */ 80 unsigned int rx_filter; 81 int started; 82 struct timer_list beacon_timer; 83}; 84 85 86struct hwsim_radiotap_hdr { 87 struct ieee80211_radiotap_header hdr; 88 u8 rt_flags; 89 u8 rt_rate; 90 __le16 rt_channel; 91 __le16 rt_chbitmask; 92} __attribute__ ((packed)); 93 94 95static int hwsim_mon_xmit(struct sk_buff *skb, struct net_device *dev) 96{ 97 /* TODO: allow packet injection */ 98 dev_kfree_skb(skb); 99 return 0; 100} 101 102 103static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, 104 struct sk_buff *tx_skb) 105{ 106 struct mac80211_hwsim_data *data = hw->priv; 107 struct sk_buff *skb; 108 struct hwsim_radiotap_hdr *hdr; 109 u16 flags; 110 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_skb); 111 struct ieee80211_rate *txrate = ieee80211_get_tx_rate(hw, info); 112 113 if (!netif_running(hwsim_mon)) 114 return; 115 116 skb = skb_copy_expand(tx_skb, sizeof(*hdr), 0, GFP_ATOMIC); 117 if (skb == NULL) 118 return; 119 120 hdr = (struct hwsim_radiotap_hdr *) skb_push(skb, sizeof(*hdr)); 121 hdr->hdr.it_version = PKTHDR_RADIOTAP_VERSION; 122 hdr->hdr.it_pad = 0; 123 hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr)); 124 hdr->hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | 125 (1 << IEEE80211_RADIOTAP_RATE) | 126 (1 << IEEE80211_RADIOTAP_CHANNEL)); 127 hdr->rt_flags = 0; 128 hdr->rt_rate = txrate->bitrate / 5; 129 hdr->rt_channel = cpu_to_le16(data->channel->center_freq); 130 flags = IEEE80211_CHAN_2GHZ; 131 if (txrate->flags & IEEE80211_RATE_ERP_G) 132 flags |= IEEE80211_CHAN_OFDM; 133 else 134 flags |= IEEE80211_CHAN_CCK; 135 hdr->rt_chbitmask = cpu_to_le16(flags); 136 137 skb->dev = hwsim_mon; 138 skb_set_mac_header(skb, 0); 139 skb->ip_summed = CHECKSUM_UNNECESSARY; 140 skb->pkt_type = PACKET_OTHERHOST; 141 skb->protocol = htons(ETH_P_802_2); 142 memset(skb->cb, 0, sizeof(skb->cb)); 143 netif_rx(skb); 144} 145 146 147static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, 148 struct sk_buff *skb) 149{ 150 struct mac80211_hwsim_data *data = hw->priv; 151 int i, ack = 0; 152 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 153 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 154 struct ieee80211_rx_status rx_status; 155 156 memset(&rx_status, 0, sizeof(rx_status)); 157 /* TODO: set mactime */ 158 rx_status.freq = data->channel->center_freq; 159 rx_status.band = data->channel->band; 160 rx_status.rate_idx = info->tx_rate_idx; 161 /* TODO: simulate signal strength (and optional packet drop) */ 162 163 /* Copy skb to all enabled radios that are on the current frequency */ 164 for (i = 0; i < hwsim_radio_count; i++) { 165 struct mac80211_hwsim_data *data2; 166 struct sk_buff *nskb; 167 168 if (hwsim_radios[i] == NULL || hwsim_radios[i] == hw) 169 continue; 170 data2 = hwsim_radios[i]->priv; 171 if (!data2->started || !data2->radio_enabled || 172 data->channel->center_freq != data2->channel->center_freq) 173 continue; 174 175 nskb = skb_copy(skb, GFP_ATOMIC); 176 if (nskb == NULL) 177 continue; 178 179 if (memcmp(hdr->addr1, hwsim_radios[i]->wiphy->perm_addr, 180 ETH_ALEN) == 0) 181 ack = 1; 182 ieee80211_rx_irqsafe(hwsim_radios[i], nskb, &rx_status); 183 } 184 185 return ack; 186} 187 188 189static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) 190{ 191 struct mac80211_hwsim_data *data = hw->priv; 192 int ack; 193 struct ieee80211_tx_info *txi; 194 195 mac80211_hwsim_monitor_rx(hw, skb); 196 197 if (skb->len < 10) { 198 /* Should not happen; just a sanity check for addr1 use */ 199 dev_kfree_skb(skb); 200 return NETDEV_TX_OK; 201 } 202 203 if (!data->radio_enabled) { 204 printk(KERN_DEBUG "%s: dropped TX frame since radio " 205 "disabled\n", wiphy_name(hw->wiphy)); 206 dev_kfree_skb(skb); 207 return NETDEV_TX_OK; 208 } 209 210 ack = mac80211_hwsim_tx_frame(hw, skb); 211 212 txi = IEEE80211_SKB_CB(skb); 213 memset(&txi->status, 0, sizeof(txi->status)); 214 if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK)) { 215 if (ack) 216 txi->flags |= IEEE80211_TX_STAT_ACK; 217 else 218 txi->status.excessive_retries = 1; 219 } 220 ieee80211_tx_status_irqsafe(hw, skb); 221 return NETDEV_TX_OK; 222} 223 224 225static int mac80211_hwsim_start(struct ieee80211_hw *hw) 226{ 227 struct mac80211_hwsim_data *data = hw->priv; 228 printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__); 229 data->started = 1; 230 return 0; 231} 232 233 234static void mac80211_hwsim_stop(struct ieee80211_hw *hw) 235{ 236 struct mac80211_hwsim_data *data = hw->priv; 237 data->started = 0; 238 printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__); 239} 240 241 242static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, 243 struct ieee80211_if_init_conf *conf) 244{ 245 DECLARE_MAC_BUF(mac); 246 printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%s)\n", 247 wiphy_name(hw->wiphy), __func__, conf->type, 248 print_mac(mac, conf->mac_addr)); 249 return 0; 250} 251 252 253static void mac80211_hwsim_remove_interface( 254 struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) 255{ 256 DECLARE_MAC_BUF(mac); 257 printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%s)\n", 258 wiphy_name(hw->wiphy), __func__, conf->type, 259 print_mac(mac, conf->mac_addr)); 260} 261 262 263static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, 264 struct ieee80211_vif *vif) 265{ 266 struct ieee80211_hw *hw = arg; 267 struct sk_buff *skb; 268 struct ieee80211_tx_info *info; 269 270 if (vif->type != IEEE80211_IF_TYPE_AP) 271 return; 272 273 skb = ieee80211_beacon_get(hw, vif); 274 if (skb == NULL) 275 return; 276 info = IEEE80211_SKB_CB(skb); 277 278 mac80211_hwsim_monitor_rx(hw, skb); 279 mac80211_hwsim_tx_frame(hw, skb); 280 dev_kfree_skb(skb); 281} 282 283 284static void mac80211_hwsim_beacon(unsigned long arg) 285{ 286 struct ieee80211_hw *hw = (struct ieee80211_hw *) arg; 287 struct mac80211_hwsim_data *data = hw->priv; 288 289 if (!data->started || !data->radio_enabled) 290 return; 291 292 ieee80211_iterate_active_interfaces_atomic( 293 hw, mac80211_hwsim_beacon_tx, hw); 294 295 data->beacon_timer.expires = jiffies + data->beacon_int; 296 add_timer(&data->beacon_timer); 297} 298 299 300static int mac80211_hwsim_config(struct ieee80211_hw *hw, 301 struct ieee80211_conf *conf) 302{ 303 struct mac80211_hwsim_data *data = hw->priv; 304 305 printk(KERN_DEBUG "%s:%s (freq=%d radio_enabled=%d beacon_int=%d)\n", 306 wiphy_name(hw->wiphy), __func__, 307 conf->channel->center_freq, conf->radio_enabled, 308 conf->beacon_int); 309 310 data->channel = conf->channel; 311 data->radio_enabled = conf->radio_enabled; 312 data->beacon_int = 1024 * conf->beacon_int / 1000 * HZ / 1000; 313 if (data->beacon_int < 1) 314 data->beacon_int = 1; 315 316 if (!data->started || !data->radio_enabled) 317 del_timer(&data->beacon_timer); 318 else 319 mod_timer(&data->beacon_timer, jiffies + data->beacon_int); 320 321 return 0; 322} 323 324 325static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw, 326 unsigned int changed_flags, 327 unsigned int *total_flags, 328 int mc_count, 329 struct dev_addr_list *mc_list) 330{ 331 struct mac80211_hwsim_data *data = hw->priv; 332 333 printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__); 334 335 data->rx_filter = 0; 336 if (*total_flags & FIF_PROMISC_IN_BSS) 337 data->rx_filter |= FIF_PROMISC_IN_BSS; 338 if (*total_flags & FIF_ALLMULTI) 339 data->rx_filter |= FIF_ALLMULTI; 340 341 *total_flags = data->rx_filter; 342} 343 344 345 346static const struct ieee80211_ops mac80211_hwsim_ops = 347{ 348 .tx = mac80211_hwsim_tx, 349 .start = mac80211_hwsim_start, 350 .stop = mac80211_hwsim_stop, 351 .add_interface = mac80211_hwsim_add_interface, 352 .remove_interface = mac80211_hwsim_remove_interface, 353 .config = mac80211_hwsim_config, 354 .configure_filter = mac80211_hwsim_configure_filter, 355}; 356 357 358static void mac80211_hwsim_free(void) 359{ 360 int i; 361 362 for (i = 0; i < hwsim_radio_count; i++) { 363 if (hwsim_radios[i]) { 364 struct mac80211_hwsim_data *data; 365 data = hwsim_radios[i]->priv; 366 ieee80211_unregister_hw(hwsim_radios[i]); 367 device_unregister(data->dev); 368 ieee80211_free_hw(hwsim_radios[i]); 369 } 370 } 371 kfree(hwsim_radios); 372 class_destroy(hwsim_class); 373} 374 375 376static struct device_driver mac80211_hwsim_driver = { 377 .name = "mac80211_hwsim" 378}; 379 380 381static void hwsim_mon_setup(struct net_device *dev) 382{ 383 dev->hard_start_xmit = hwsim_mon_xmit; 384 dev->destructor = free_netdev; 385 ether_setup(dev); 386 dev->tx_queue_len = 0; 387 dev->type = ARPHRD_IEEE80211_RADIOTAP; 388 memset(dev->dev_addr, 0, ETH_ALEN); 389 dev->dev_addr[0] = 0x12; 390} 391 392 393static int __init init_mac80211_hwsim(void) 394{ 395 int i, err = 0; 396 u8 addr[ETH_ALEN]; 397 struct mac80211_hwsim_data *data; 398 struct ieee80211_hw *hw; 399 DECLARE_MAC_BUF(mac); 400 401 if (radios < 1 || radios > 65535) 402 return -EINVAL; 403 404 hwsim_radio_count = radios; 405 hwsim_radios = kcalloc(hwsim_radio_count, 406 sizeof(struct ieee80211_hw *), GFP_KERNEL); 407 if (hwsim_radios == NULL) 408 return -ENOMEM; 409 410 hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim"); 411 if (IS_ERR(hwsim_class)) { 412 kfree(hwsim_radios); 413 return PTR_ERR(hwsim_class); 414 } 415 416 memset(addr, 0, ETH_ALEN); 417 addr[0] = 0x02; 418 419 for (i = 0; i < hwsim_radio_count; i++) { 420 printk(KERN_DEBUG "mac80211_hwsim: Initializing radio %d\n", 421 i); 422 hw = ieee80211_alloc_hw(sizeof(*data), &mac80211_hwsim_ops); 423 if (hw == NULL) { 424 printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw " 425 "failed\n"); 426 err = -ENOMEM; 427 goto failed; 428 } 429 hwsim_radios[i] = hw; 430 431 data = hw->priv; 432 data->dev = device_create_drvdata(hwsim_class, NULL, 0, hw, 433 "hwsim%d", i); 434 if (IS_ERR(data->dev)) { 435 printk(KERN_DEBUG 436 "mac80211_hwsim: device_create_drvdata " 437 "failed (%ld)\n", PTR_ERR(data->dev)); 438 err = -ENOMEM; 439 goto failed_drvdata; 440 } 441 data->dev->driver = &mac80211_hwsim_driver; 442 443 SET_IEEE80211_DEV(hw, data->dev); 444 addr[3] = i >> 8; 445 addr[4] = i; 446 SET_IEEE80211_PERM_ADDR(hw, addr); 447 448 hw->channel_change_time = 1; 449 hw->queues = 1; 450 451 memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels)); 452 memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); 453 data->band.channels = data->channels; 454 data->band.n_channels = ARRAY_SIZE(hwsim_channels); 455 data->band.bitrates = data->rates; 456 data->band.n_bitrates = ARRAY_SIZE(hwsim_rates); 457 hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band; 458 459 err = ieee80211_register_hw(hw); 460 if (err < 0) { 461 printk(KERN_DEBUG "mac80211_hwsim: " 462 "ieee80211_register_hw failed (%d)\n", err); 463 goto failed_hw; 464 } 465 466 printk(KERN_DEBUG "%s: hwaddr %s registered\n", 467 wiphy_name(hw->wiphy), 468 print_mac(mac, hw->wiphy->perm_addr)); 469 470 setup_timer(&data->beacon_timer, mac80211_hwsim_beacon, 471 (unsigned long) hw); 472 } 473 474 hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup); 475 if (hwsim_mon == NULL) 476 goto failed; 477 478 rtnl_lock(); 479 480 err = dev_alloc_name(hwsim_mon, hwsim_mon->name); 481 if (err < 0) 482 goto failed_mon; 483 484 485 err = register_netdevice(hwsim_mon); 486 if (err < 0) 487 goto failed_mon; 488 489 rtnl_unlock(); 490 491 return 0; 492 493failed_mon: 494 rtnl_unlock(); 495 free_netdev(hwsim_mon); 496 mac80211_hwsim_free(); 497 return err; 498 499failed_hw: 500 device_unregister(data->dev); 501failed_drvdata: 502 ieee80211_free_hw(hw); 503 hwsim_radios[i] = NULL; 504failed: 505 mac80211_hwsim_free(); 506 return err; 507} 508 509 510static void __exit exit_mac80211_hwsim(void) 511{ 512 printk(KERN_DEBUG "mac80211_hwsim: unregister %d radios\n", 513 hwsim_radio_count); 514 515 unregister_netdev(hwsim_mon); 516 mac80211_hwsim_free(); 517} 518 519 520module_init(init_mac80211_hwsim); 521module_exit(exit_mac80211_hwsim);