Skip to content

Commit 4e81b72

Browse files
Add manual MCS configuration via set_bitrate_mask
Implement the set_bitrate_mask callback in cfg80211_ops to support manual MCS settings using `iw dev <interface> set bitrates ht-mcs-2.4 <mcs_index>`, addressing reviewer feedback. Store the selected MCS in vwifi_vif->manual_mcs and track its state with vwifi_vif->manual_mcs_set. Support MCS indices 7, 15, 23, and 31, with validation and logging. Enable High Throughput (HT) in nf_band_2ghz with MCS 0–31, using IEEE80211_HT_CAP_SUP_WIDTH_20_40 for 20 MHz compatibility. Fix compilation errors by initializing rx_mask statically and removing const qualifiers from channel/rate arrays. Improve vwifi_connect to ensure stable association. Tested with `iw dev vw1 set bitrates ht-mcs-2.4 15`, achieving MCS 15 at 130.0 MBit/s (bitrate calculation pending refinement to ~52 MBit/s). Test commands format $sudo ip netns exec ns1 iw dev vw1 link $sudo ip netns exec ns1 iw dev vw1 set bitrates ht-mcs-2.4 15 /*(changable 7,15,23,31)*/ $sudo ip netns exec ns1 iw dev vw1 link
1 parent cf0561f commit 4e81b72

File tree

2 files changed

+144
-51
lines changed

2 files changed

+144
-51
lines changed

scripts/hostapd.conf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ interface=vw0
22
driver=nl80211
33
debug=1
44
ctrl_interface=/var/run/hostapd
5-
ctrl_interface_group=0
5+
ctrl_interface_group=root
66
channel=6
77
ssid=test
88
wpa=2
@@ -12,4 +12,4 @@ wpa_pairwise=CCMP
1212

1313
# Beacon interval (kibi-us : 1.024 ms)
1414
beacon_int=100
15-
dtim_period=1
15+
dtim_period=1

vwifi.c

Lines changed: 142 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ struct vwifi_vif {
8888
struct wireless_dev wdev;
8989
struct net_device *ndev;
9090
struct net_device_stats stats;
91+
int manual_mcs; /* ADDED: Store user-specified MCS */
92+
bool manual_mcs_set; /* ADDED: Flag to indicate manual MCS override */
9193

9294
size_t ssid_len;
9395
/* Currently connected BSS id */
@@ -1345,7 +1347,6 @@ static int vwifi_get_station(struct wiphy *wiphy,
13451347
struct station_info *sinfo)
13461348
{
13471349
struct vwifi_vif *vif = ndev_get_vwifi_vif(dev);
1348-
13491350
bool found_sta = false;
13501351
switch (dev->ieee80211_ptr->iftype) {
13511352
case NL80211_IFTYPE_AP:;
@@ -1439,38 +1440,52 @@ static int vwifi_get_station(struct wiphy *wiphy,
14391440

14401441

14411442

1442-
/* Log byte counters for debugging */
1443-
pr_info("vwifi: Station %pM tx_bytes %llu, rx_bytes %llu\n", mac,
1444-
sinfo->tx_bytes, sinfo->rx_bytes);
1445-
1446-
/* Dynamic modulation based on signal strength */
1443+
/* Checks vif->manual_mcs_set to use vif->manual_mcs if set;
1444+
* Assigns modulation string for manual MCS ; else auto change based
1445+
* on signal strength
1446+
*/
14471447
int mcs_index;
14481448
const char *modulation;
1449-
unsigned int data_rate_mbps;
1450-
if (sinfo->signal > -50) {
1451-
/* Strong signal: 64-QAM, MCS 31 */
1452-
mcs_index = 31;
1453-
modulation = "64-QAM";
1454-
} else if (sinfo->signal > -70 && sinfo->signal <= -50) {
1455-
/* Medium signal: 16-QAM, MCS 23 */
1456-
mcs_index = 23;
1457-
modulation = "16-QAM";
1458-
} else if (sinfo->signal > -90 && sinfo->signal <= -70) {
1459-
/* Weak signal: QPSK, MCS 15 */
1460-
mcs_index = 15;
1461-
modulation = "QPSK";
1449+
if (vif->manual_mcs_set) {
1450+
mcs_index = vif->manual_mcs;
1451+
switch (mcs_index) {
1452+
case 7:
1453+
modulation = "BPSK";
1454+
break;
1455+
case 15:
1456+
modulation = "QPSK";
1457+
break;
1458+
case 23:
1459+
modulation = "16-QAM";
1460+
break;
1461+
case 31:
1462+
modulation = "64-QAM";
1463+
break;
1464+
default:
1465+
modulation = "Unknown";
1466+
break;
1467+
}
1468+
pr_info("vwifi: Station %pM using manual MCS %d (%s)\n", mac, mcs_index,
1469+
modulation);
14621470
} else {
1463-
/* Very weak signal: BPSK, MCS 7 */
1464-
mcs_index = 7;
1465-
modulation = "BPSK";
1471+
if (sinfo->signal > -50) {
1472+
mcs_index = 31;
1473+
modulation = "64-QAM";
1474+
} else if (sinfo->signal > -70 && sinfo->signal <= -50) {
1475+
mcs_index = 23;
1476+
modulation = "16-QAM";
1477+
} else if (sinfo->signal > -90 && sinfo->signal <= -70) {
1478+
mcs_index = 15;
1479+
modulation = "QPSK";
1480+
} else {
1481+
mcs_index = 7;
1482+
modulation = "BPSK";
1483+
}
1484+
pr_info(
1485+
"vwifi: Station %pM signal %d dBm, using modulation %s (MCS %d)\n",
1486+
mac, sinfo->signal, modulation, mcs_index);
14661487
}
14671488

1468-
/* Log signal, modulation, and data rate for debugging */
1469-
pr_info(
1470-
"vwifi: Station %pM signal %d dBm, using modulation %s (MCS %d, %u "
1471-
"Mbps)\n",
1472-
mac, sinfo->signal, modulation, mcs_index, data_rate_mbps);
1473-
14741489
/* Configure RX and TX rates */
14751490
sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS;
14761491
sinfo->rxrate.mcs = mcs_index;
@@ -1728,13 +1743,8 @@ static int vwifi_start_ap(struct wiphy *wiphy,
17281743

17291744
/* Initialize hrtimer of beacon */
17301745
pr_info("vwifi: init beacon_timer.\n");
1731-
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
1732-
hrtimer_setup(&vif->beacon_timer, vwifi_beacon, CLOCK_MONOTONIC,
1733-
HRTIMER_MODE_ABS_SOFT);
1734-
#else
17351746
hrtimer_init(&vif->beacon_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_SOFT);
17361747
vif->beacon_timer.function = vwifi_beacon;
1737-
#endif
17381748

17391749
if (!hrtimer_is_queued(&vif->beacon_timer)) {
17401750
u64 tsf, until_tbtt;
@@ -2201,6 +2211,66 @@ static int vwifi_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
22012211

22022212
return 0;
22032213
}
2214+
/* Callback to handle manual bitrate configuration via iw */
2215+
static int vwifi_set_bitrate_mask(struct wiphy *wiphy,
2216+
struct net_device *dev,
2217+
unsigned int link_id,
2218+
const u8 *peer,
2219+
const struct cfg80211_bitrate_mask *mask)
2220+
{
2221+
struct vwifi_vif *vif = netdev_priv(dev);
2222+
int mcs_index = -1;
2223+
2224+
if (!vif) {
2225+
pr_err("vwifi: Failed to get vwifi_vif for dev %s\n", dev->name);
2226+
return -EINVAL;
2227+
}
2228+
2229+
if (vif->sme_state != SME_CONNECTED) {
2230+
pr_err("vwifi: Dev %s not connected, cannot set bitrate\n", dev->name);
2231+
return -EINVAL;
2232+
}
2233+
2234+
pr_info("vwifi: set_bitrate_mask called for dev %s, link_id %u, peer %pM\n",
2235+
dev->name, link_id, peer ? peer : vif->bssid);
2236+
pr_info("vwifi: 2.4GHz MCS mask: %02x %02x %02x %02x\n",
2237+
mask->control[NL80211_BAND_2GHZ].ht_mcs[0],
2238+
mask->control[NL80211_BAND_2GHZ].ht_mcs[1],
2239+
mask->control[NL80211_BAND_2GHZ].ht_mcs[2],
2240+
mask->control[NL80211_BAND_2GHZ].ht_mcs[3]);
2241+
2242+
/* Find the requested MCS index */
2243+
for (int i = 0; i < 4; i++) {
2244+
if (mask->control[NL80211_BAND_2GHZ].ht_mcs[i]) {
2245+
for (int j = 0; j < 8; j++) {
2246+
if (mask->control[NL80211_BAND_2GHZ].ht_mcs[i] & (1 << j)) {
2247+
mcs_index = i * 8 + j;
2248+
pr_info("vwifi: Requested MCS index %d\n", mcs_index);
2249+
break;
2250+
}
2251+
}
2252+
if (mcs_index != -1)
2253+
break;
2254+
}
2255+
}
2256+
2257+
if (mcs_index == -1) {
2258+
pr_err("vwifi: No valid MCS index found\n");
2259+
return -EINVAL;
2260+
}
2261+
2262+
if (mcs_index != 7 && mcs_index != 15 && mcs_index != 23 &&
2263+
mcs_index != 31) {
2264+
pr_err("vwifi: Unsupported MCS index %d\n", mcs_index);
2265+
return -EINVAL;
2266+
}
2267+
2268+
vif->manual_mcs = mcs_index;
2269+
vif->manual_mcs_set = true;
2270+
pr_info("vwifi: Set manual MCS %d for dev %s\n", mcs_index, dev->name);
2271+
2272+
return 0;
2273+
}
22042274

22052275
/* Structure of functions for FullMAC 80211 drivers. Functions implemented
22062276
* along with fields/flags in the wiphy structure represent driver features.
@@ -2226,31 +2296,35 @@ static struct cfg80211_ops vwifi_cfg_ops = {
22262296
.get_tx_power = vwifi_get_tx_power,
22272297
.join_ibss = vwifi_join_ibss,
22282298
.leave_ibss = vwifi_leave_ibss,
2299+
.set_bitrate_mask = vwifi_set_bitrate_mask,
22292300
};
22302301

22312302
/* Macro for defining 2GHZ channel array */
2232-
#define CHAN_2GHZ(channel, freq) \
2233-
{ \
2234-
.band = NL80211_BAND_2GHZ, .hw_value = (channel), \
2235-
.center_freq = (freq), \
2303+
#define CHAN_2GHZ(channel, freq) \
2304+
{ \
2305+
.band = NL80211_BAND_2GHZ, \
2306+
.hw_value = (channel), \
2307+
.center_freq = (freq), \
22362308
}
22372309

22382310
/* Macro for defining 5GHZ channel array */
2239-
#define CHAN_5GHZ(channel) \
2240-
{ \
2241-
.band = NL80211_BAND_5GHZ, .hw_value = (channel), \
2242-
.center_freq = 5000 + (5 * (channel)), \
2311+
#define CHAN_5GHZ(channel) \
2312+
{ \
2313+
.band = NL80211_BAND_5GHZ, \
2314+
.hw_value = (channel), \
2315+
.center_freq = 5000 + (5 * (channel)), \
22432316
}
22442317

22452318

22462319
/* Macro for defining rate table */
2247-
#define RATE_ENT(_rate, _hw_value) \
2248-
{ \
2249-
.bitrate = (_rate), .hw_value = (_hw_value), \
2320+
#define RATE_ENT(_rate, _hw_value) \
2321+
{ \
2322+
.bitrate = (_rate), \
2323+
.hw_value = (_hw_value), \
22502324
}
22512325

22522326
/* Array of "supported" channels in 2GHz band. It is required for wiphy. */
2253-
static const struct ieee80211_channel vwifi_supported_channels_2ghz[] = {
2327+
static struct ieee80211_channel vwifi_supported_channels_2ghz[] = {
22542328
CHAN_2GHZ(1, 2412), CHAN_2GHZ(2, 2417), CHAN_2GHZ(3, 2422),
22552329
CHAN_2GHZ(4, 2427), CHAN_2GHZ(5, 2432), CHAN_2GHZ(6, 2437),
22562330
CHAN_2GHZ(7, 2442), CHAN_2GHZ(8, 2447), CHAN_2GHZ(9, 2452),
@@ -2273,16 +2347,35 @@ static const struct ieee80211_channel vwifi_supported_channels_5ghz[] = {
22732347
/* Array of supported rates, required to support those next rates
22742348
* for 2GHz and 5GHz band.
22752349
*/
2276-
static const struct ieee80211_rate vwifi_supported_rates[] = {
2350+
static struct ieee80211_rate vwifi_supported_rates[] = {
22772351
RATE_ENT(10, 0x1), RATE_ENT(20, 0x2), RATE_ENT(55, 0x4),
22782352
RATE_ENT(110, 0x8), RATE_ENT(60, 0x10), RATE_ENT(90, 0x20),
22792353
RATE_ENT(120, 0x40), RATE_ENT(180, 0x80), RATE_ENT(240, 0x100),
22802354
RATE_ENT(360, 0x200), RATE_ENT(480, 0x400), RATE_ENT(540, 0x800),
22812355
};
22822356

2283-
/* Describes supported band of 2GHz. */
2284-
static struct ieee80211_supported_band nf_band_2ghz;
2285-
2357+
static struct ieee80211_supported_band nf_band_2ghz = {
2358+
.band = NL80211_BAND_2GHZ,
2359+
.channels = vwifi_supported_channels_2ghz,
2360+
.n_channels = ARRAY_SIZE(vwifi_supported_channels_2ghz),
2361+
.bitrates = vwifi_supported_rates,
2362+
.n_bitrates = ARRAY_SIZE(vwifi_supported_rates),
2363+
.ht_cap =
2364+
{
2365+
.ht_supported = true,
2366+
.cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_GRN_FLD |
2367+
IEEE80211_HT_CAP_MAX_AMSDU |
2368+
IEEE80211_HT_CAP_SUP_WIDTH_20_40,
2369+
.mcs =
2370+
{
2371+
.rx_mask = {0xff, 0xff, 0xff, 0xff}, /* MCS 0-31 */
2372+
.rx_highest = cpu_to_le16(300),
2373+
.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
2374+
},
2375+
.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
2376+
.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
2377+
},
2378+
};
22862379
/* Describes supported band of 5GHz. */
22872380
static struct ieee80211_supported_band nf_band_5ghz;
22882381

0 commit comments

Comments
 (0)