Skip to content

Commit a612f14

Browse files
committed
Support manual bitrate mask control
Add support for setting cfg80211_bitrate_mask via set_bitrate_mask(). This enables users to manually specify legacy bitrates using the iw, which influences the simulated transmission latency. The packet latency logic has been updated to reflect real-world behavior by making delay inversely proportional to the configured bitrate. When a valid bitrate mask is applied, the delay is calculated as: (datalen * 8 * 1000) / bitrate_kbps If no valid bitrate is set, fallback to default delay is used. This change improves fidelity of wireless emulation by making packet timing sensitive to user configuration and network rate conditions.
1 parent 62a3dd8 commit a612f14

File tree

1 file changed

+115
-9
lines changed

1 file changed

+115
-9
lines changed

vwifi.c

Lines changed: 115 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <linux/etherdevice.h>
22
#include <linux/hashtable.h>
33
#include <linux/hrtimer.h>
4+
#include <linux/kernel.h>
45
#include <linux/module.h>
56
#include <linux/mutex.h>
67
#include <linux/random.h>
@@ -35,6 +36,12 @@ MODULE_DESCRIPTION("virtual cfg80211 driver");
3536

3637
#define SCAN_TIMEOUT_MS 100 /*< millisecond */
3738

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+
3845
/* Note: vwifi_cipher_suites is an array of int defining which cipher suites
3946
* are supported. A pointer to this array and the number of entries is passed
4047
* on to upper layers.
@@ -88,6 +95,7 @@ struct vwifi_vif {
8895
struct wireless_dev wdev;
8996
struct net_device *ndev;
9097
struct net_device_stats stats;
98+
struct cfg80211_bitrate_mask bitrate_mask;
9199

92100
size_t ssid_len;
93101
/* Currently connected BSS id */
@@ -206,6 +214,10 @@ static int station = 2;
206214
module_param(station, int, 0444);
207215
MODULE_PARM_DESC(station, "Number of virtual interfaces running in STA mode.");
208216

217+
static int ap = 0;
218+
module_param(ap, int, 0444);
219+
MODULE_PARM_DESC(ap, "number of AP mode interfaces to create");
220+
209221
/* Global context */
210222
static struct vwifi_context *vwifi = NULL;
211223

@@ -548,6 +560,46 @@ static void inform_bss(struct vwifi_vif *vif)
548560
}
549561
}
550562

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+
551603
/* Helper function that prepares a structure with self-defined BSS information
552604
* and "informs" the kernel about the "new" Independent BSS.
553605
*/
@@ -871,6 +923,26 @@ static int __vwifi_ndo_start_xmit(struct vwifi_vif *vif,
871923
eth_hdr->h_source);
872924
}
873925

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+
}
874946
/* Directly send to rx_queue, simulate the rx interrupt */
875947
vwifi_rx(dest_vif->ndev);
876948

@@ -1425,15 +1497,40 @@ static int vwifi_get_station(struct wiphy *wiphy,
14251497
* https://semfionetworks.com/blog/mcs-table-updated-with-80211ax-data-rates/
14261498
* IEEE 802.11n : https://zh.wikipedia.org/zh-tw/IEEE_802.11n
14271499
*/
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+
}
14371534
return 0;
14381535
}
14391536

@@ -2170,6 +2267,7 @@ static struct cfg80211_ops vwifi_cfg_ops = {
21702267
.get_tx_power = vwifi_get_tx_power,
21712268
.join_ibss = vwifi_join_ibss,
21722269
.leave_ibss = vwifi_leave_ibss,
2270+
.set_bitrate_mask = vwifi_set_bitrate_mask,
21732271
};
21742272

21752273
/* Macro for defining 2GHZ channel array */
@@ -3340,6 +3438,14 @@ static int __init vwifi_init(void)
33403438
goto interface_add;
33413439
}
33423440

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+
33433449
nl_sk = netlink_kernel_create(&init_net, NETLINK_USERSOCK, &nl_config);
33443450
if (!nl_sk) {
33453451
pr_info("Error creating netlink socket\n");

0 commit comments

Comments
 (0)