|
1 | 1 | #include <linux/etherdevice.h> |
2 | 2 | #include <linux/hashtable.h> |
3 | 3 | #include <linux/hrtimer.h> |
| 4 | +#include <linux/kernel.h> |
4 | 5 | #include <linux/module.h> |
5 | 6 | #include <linux/mutex.h> |
6 | 7 | #include <linux/random.h> |
@@ -35,6 +36,12 @@ MODULE_DESCRIPTION("virtual cfg80211 driver"); |
35 | 36 |
|
36 | 37 | #define SCAN_TIMEOUT_MS 100 /*< millisecond */ |
37 | 38 |
|
| 39 | +#define VWIFI_ALL_RATES_2GHZ 0x0FFF |
| 40 | +#define VWIFI_ALL_RATES_5GHZ 0x0FF0 // bit 4~11 set |
| 41 | + |
| 42 | +static const struct ieee80211_rate vwifi_supported_rates[]; |
| 43 | +static const int vwifi_supported_rates_count = 12; |
| 44 | + |
38 | 45 | /* Note: vwifi_cipher_suites is an array of int defining which cipher suites |
39 | 46 | * are supported. A pointer to this array and the number of entries is passed |
40 | 47 | * on to upper layers. |
@@ -88,6 +95,7 @@ struct vwifi_vif { |
88 | 95 | struct wireless_dev wdev; |
89 | 96 | struct net_device *ndev; |
90 | 97 | struct net_device_stats stats; |
| 98 | + struct cfg80211_bitrate_mask bitrate_mask; |
91 | 99 |
|
92 | 100 | size_t ssid_len; |
93 | 101 | /* Currently connected BSS id */ |
@@ -206,6 +214,10 @@ static int station = 2; |
206 | 214 | module_param(station, int, 0444); |
207 | 215 | MODULE_PARM_DESC(station, "Number of virtual interfaces running in STA mode."); |
208 | 216 |
|
| 217 | +static int ap = 0; |
| 218 | +module_param(ap, int, 0444); |
| 219 | +MODULE_PARM_DESC(ap, "number of AP mode interfaces to create"); |
| 220 | + |
209 | 221 | /* Global context */ |
210 | 222 | static struct vwifi_context *vwifi = NULL; |
211 | 223 |
|
@@ -548,6 +560,46 @@ static void inform_bss(struct vwifi_vif *vif) |
548 | 560 | } |
549 | 561 | } |
550 | 562 |
|
| 563 | +static int vwifi_set_bitrate_mask(struct wiphy *wiphy, |
| 564 | + struct net_device *dev, |
| 565 | + unsigned int link_id, |
| 566 | + const u8 *peer, |
| 567 | + const struct cfg80211_bitrate_mask *mask) |
| 568 | +{ |
| 569 | + struct vwifi_vif *vif = netdev_priv(dev); |
| 570 | + |
| 571 | + if (!(dev->flags & IFF_UP) || !netif_running(dev)) { |
| 572 | + return -ENETDOWN; |
| 573 | + } |
| 574 | + |
| 575 | + bool has_valid_rate = false; |
| 576 | + |
| 577 | + for (int band = 0; band < NUM_NL80211_BANDS; band++) { |
| 578 | + u32 user_mask = mask->control[band].legacy; |
| 579 | + u32 basic_mask = 0; |
| 580 | + |
| 581 | + if (band == NL80211_BAND_2GHZ) |
| 582 | + basic_mask = VWIFI_ALL_RATES_2GHZ; |
| 583 | + else if (band == NL80211_BAND_5GHZ) |
| 584 | + basic_mask = VWIFI_ALL_RATES_5GHZ; |
| 585 | + else |
| 586 | + continue; |
| 587 | + |
| 588 | + if (user_mask & basic_mask) { |
| 589 | + has_valid_rate = true; |
| 590 | + break; |
| 591 | + } |
| 592 | + } |
| 593 | + |
| 594 | + if (!has_valid_rate) |
| 595 | + return -EINVAL; |
| 596 | + |
| 597 | + memcpy(&vif->bitrate_mask, mask, sizeof(*mask)); |
| 598 | + pr_info("vwifi: bitrate mask saved. legacy 2.4GHz = 0x%x\n", |
| 599 | + mask->control[NL80211_BAND_2GHZ].legacy); |
| 600 | + return 0; |
| 601 | +} |
| 602 | + |
551 | 603 | /* Helper function that prepares a structure with self-defined BSS information |
552 | 604 | * and "informs" the kernel about the "new" Independent BSS. |
553 | 605 | */ |
@@ -871,6 +923,26 @@ static int __vwifi_ndo_start_xmit(struct vwifi_vif *vif, |
871 | 923 | eth_hdr->h_source); |
872 | 924 | } |
873 | 925 |
|
| 926 | + int bitrate_kbps = 0; |
| 927 | + const struct cfg80211_bitrate_mask *mask = &vif->bitrate_mask; |
| 928 | + |
| 929 | + for (int band = 0; band < NUM_NL80211_BANDS; band++) { |
| 930 | + u32 mask_val = mask->control[band].legacy; |
| 931 | + if (mask_val) { |
| 932 | + for (int i = 0; i < vwifi_supported_rates_count; i++) { |
| 933 | + if (mask_val & (1 << i)) { |
| 934 | + bitrate_kbps = vwifi_supported_rates[i].bitrate * 100; |
| 935 | + break; |
| 936 | + } |
| 937 | + } |
| 938 | + break; |
| 939 | + } |
| 940 | + } |
| 941 | + |
| 942 | + if (bitrate_kbps > 0) { |
| 943 | + int delay_us = (datalen * 8 * 1000) / bitrate_kbps; |
| 944 | + udelay(delay_us); |
| 945 | + } |
874 | 946 | /* Directly send to rx_queue, simulate the rx interrupt */ |
875 | 947 | vwifi_rx(dest_vif->ndev); |
876 | 948 |
|
@@ -1425,15 +1497,40 @@ static int vwifi_get_station(struct wiphy *wiphy, |
1425 | 1497 | * https://semfionetworks.com/blog/mcs-table-updated-with-80211ax-data-rates/ |
1426 | 1498 | * IEEE 802.11n : https://zh.wikipedia.org/zh-tw/IEEE_802.11n |
1427 | 1499 | */ |
1428 | | - sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS; |
1429 | | - sinfo->rxrate.mcs = 31; |
1430 | | - sinfo->rxrate.bw = RATE_INFO_BW_20; |
1431 | | - sinfo->rxrate.n_bonded_ch = 1; |
1432 | | - |
1433 | | - sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; |
1434 | | - sinfo->txrate.mcs = 31; |
1435 | | - sinfo->txrate.bw = RATE_INFO_BW_20; |
1436 | | - sinfo->txrate.n_bonded_ch = 1; |
| 1500 | + const struct cfg80211_bitrate_mask *mask = &vif->bitrate_mask; |
| 1501 | + bool legacy_rate_set = false; |
| 1502 | + |
| 1503 | + for (int band = 0; band < NUM_NL80211_BANDS; band++) { |
| 1504 | + u32 mask_val = mask->control[band].legacy; |
| 1505 | + if (mask_val) { |
| 1506 | + int bitrate = 0; |
| 1507 | + for (int i = 0; i < 32; i++) { |
| 1508 | + if (mask_val & (1 << i)) { |
| 1509 | + bitrate = vwifi_supported_rates[i].bitrate; |
| 1510 | + break; |
| 1511 | + } |
| 1512 | + } |
| 1513 | + |
| 1514 | + if (bitrate > 0) { |
| 1515 | + sinfo->txrate.legacy = bitrate; |
| 1516 | + sinfo->rxrate.legacy = bitrate; |
| 1517 | + legacy_rate_set = true; |
| 1518 | + break; |
| 1519 | + } |
| 1520 | + } |
| 1521 | + } |
| 1522 | + |
| 1523 | + if (!legacy_rate_set) { |
| 1524 | + sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; |
| 1525 | + sinfo->txrate.mcs = 31; |
| 1526 | + sinfo->txrate.bw = RATE_INFO_BW_20; |
| 1527 | + sinfo->txrate.n_bonded_ch = 1; |
| 1528 | + |
| 1529 | + sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS; |
| 1530 | + sinfo->rxrate.mcs = 31; |
| 1531 | + sinfo->rxrate.bw = RATE_INFO_BW_20; |
| 1532 | + sinfo->rxrate.n_bonded_ch = 1; |
| 1533 | + } |
1437 | 1534 | return 0; |
1438 | 1535 | } |
1439 | 1536 |
|
@@ -2170,6 +2267,7 @@ static struct cfg80211_ops vwifi_cfg_ops = { |
2170 | 2267 | .get_tx_power = vwifi_get_tx_power, |
2171 | 2268 | .join_ibss = vwifi_join_ibss, |
2172 | 2269 | .leave_ibss = vwifi_leave_ibss, |
| 2270 | + .set_bitrate_mask = vwifi_set_bitrate_mask, |
2173 | 2271 | }; |
2174 | 2272 |
|
2175 | 2273 | /* Macro for defining 2GHZ channel array */ |
@@ -3340,6 +3438,14 @@ static int __init vwifi_init(void) |
3340 | 3438 | goto interface_add; |
3341 | 3439 | } |
3342 | 3440 |
|
| 3441 | + for (int i = 0; i < ap; ++i) { |
| 3442 | + struct wiphy *wiphy = vwifi_cfg80211_add(); |
| 3443 | + if (!wiphy) |
| 3444 | + goto cfg80211_add; |
| 3445 | + if (!vwifi_interface_add(wiphy, i)) |
| 3446 | + goto interface_add; |
| 3447 | + } |
| 3448 | + |
3343 | 3449 | nl_sk = netlink_kernel_create(&init_net, NETLINK_USERSOCK, &nl_config); |
3344 | 3450 | if (!nl_sk) { |
3345 | 3451 | pr_info("Error creating netlink socket\n"); |
|
0 commit comments