|
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