diff --git a/scripts/hostapd.conf b/scripts/hostapd.conf index e55bb22..bdae256 100644 --- a/scripts/hostapd.conf +++ b/scripts/hostapd.conf @@ -2,7 +2,7 @@ interface=vw0 driver=nl80211 debug=1 ctrl_interface=/var/run/hostapd -ctrl_interface_group=0 +ctrl_interface_group=root channel=6 ssid=test wpa=2 @@ -12,4 +12,4 @@ wpa_pairwise=CCMP # Beacon interval (kibi-us : 1.024 ms) beacon_int=100 -dtim_period=1 \ No newline at end of file +dtim_period=1 diff --git a/vwifi.c b/vwifi.c index eebd149..d936032 100644 --- a/vwifi.c +++ b/vwifi.c @@ -88,7 +88,8 @@ struct vwifi_vif { struct wireless_dev wdev; struct net_device *ndev; struct net_device_stats stats; - + int manual_mcs; + bool manual_mcs_set; size_t ssid_len; /* Currently connected BSS id */ u8 bssid[ETH_ALEN]; @@ -1345,7 +1346,6 @@ static int vwifi_get_station(struct wiphy *wiphy, struct station_info *sinfo) { struct vwifi_vif *vif = ndev_get_vwifi_vif(dev); - bool found_sta = false; switch (dev->ieee80211_ptr->iftype) { case NL80211_IFTYPE_AP:; @@ -1403,8 +1403,18 @@ static int vwifi_get_station(struct wiphy *wiphy, sinfo->tx_failed = vif->stats.tx_dropped; sinfo->tx_bytes = vif->stats.tx_bytes; sinfo->rx_bytes = vif->stats.rx_bytes; + + + /* Log byte counters for debugging */ + pr_info( + "vwifi: Station %pM tx_bytes %llu, rx_bytes %llu, tx_packets %u, " + "rx_packets %u, tx_failed %u\n", + mac, sinfo->tx_bytes, sinfo->rx_bytes, sinfo->tx_packets, + sinfo->rx_packets, sinfo->tx_failed); + /* For CFG80211_SIGNAL_TYPE_MBM, value is expressed in dBm */ sinfo->signal = rand_int_smooth(-100, -30, jiffies); + pr_info("vwifi: Station %pM signal %d dBm (raw)\n", mac, sinfo->signal); sinfo->inactive_time = jiffies_to_msecs(jiffies - vif->active_time); /* * Using 802.11n (HT) as the PHY, configure as follows: @@ -1425,18 +1435,72 @@ static int vwifi_get_station(struct wiphy *wiphy, * https://semfionetworks.com/blog/mcs-table-updated-with-80211ax-data-rates/ * IEEE 802.11n : https://zh.wikipedia.org/zh-tw/IEEE_802.11n */ - sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS; - sinfo->rxrate.mcs = 31; + + + + /* Checks vif->manual_mcs_set to use vif->manual_mcs if set; + * Assigns modulation string for manual MCS ; else auto change based + * on signal strength + */ + int mcs_index; + const char *modulation; + if (vif->manual_mcs_set) { + mcs_index = vif->manual_mcs; + switch (mcs_index) { + case 7: + modulation = "BPSK"; + break; + case 15: + modulation = "QPSK"; + break; + case 23: + modulation = "16-QAM"; + break; + case 31: + modulation = "64-QAM"; + break; + default: + modulation = "Unknown"; + break; + } + pr_info("vwifi: Station %pM using manual MCS %d (%s)\n", mac, mcs_index, + modulation); + } else { + if (sinfo->signal > -50) { + mcs_index = 31; + modulation = "64-QAM"; + } else if (sinfo->signal > -70 && sinfo->signal <= -50) { + mcs_index = 23; + modulation = "16-QAM"; + } else if (sinfo->signal > -90 && sinfo->signal <= -70) { + mcs_index = 15; + modulation = "QPSK"; + } else { + mcs_index = 7; + modulation = "BPSK"; + } + pr_info( + "vwifi: Station %pM signal %d dBm, using modulation %s (MCS %d)\n", + mac, sinfo->signal, modulation, mcs_index); + } + + /* Configure RX and TX rates */ + sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS; + sinfo->rxrate.mcs = mcs_index; sinfo->rxrate.bw = RATE_INFO_BW_20; sinfo->rxrate.n_bonded_ch = 1; - sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; - sinfo->txrate.mcs = 31; + sinfo->txrate.flags = RATE_INFO_FLAGS_MCS; + sinfo->txrate.mcs = mcs_index; sinfo->txrate.bw = RATE_INFO_BW_20; sinfo->txrate.n_bonded_ch = 1; + + /* Log rate configuration for verification */ + pr_info("vwifi: Station %pM txrate MCS %d, rxrate MCS %d\n", mac, + sinfo->txrate.mcs, sinfo->rxrate.mcs); + return 0; } - /* dump station callback -- resume dump at index @idx */ static int vwifi_dump_station(struct wiphy *wiphy, struct net_device *dev, @@ -2150,6 +2214,66 @@ static int vwifi_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) return 0; } +/* Callback to handle manual bitrate configuration via iw */ +static int vwifi_set_bitrate_mask(struct wiphy *wiphy, + struct net_device *dev, + unsigned int link_id, + const u8 *peer, + const struct cfg80211_bitrate_mask *mask) +{ + struct vwifi_vif *vif = netdev_priv(dev); + int mcs_index = -1; + + if (!vif) { + pr_err("vwifi: Failed to get vwifi_vif for dev %s\n", dev->name); + return -EINVAL; + } + + if (vif->sme_state != SME_CONNECTED) { + pr_err("vwifi: Dev %s not connected, cannot set bitrate\n", dev->name); + return -EINVAL; + } + + pr_info("vwifi: set_bitrate_mask called for dev %s, link_id %u, peer %pM\n", + dev->name, link_id, peer ? peer : vif->bssid); + pr_info("vwifi: 2.4GHz MCS mask: %02x %02x %02x %02x\n", + mask->control[NL80211_BAND_2GHZ].ht_mcs[0], + mask->control[NL80211_BAND_2GHZ].ht_mcs[1], + mask->control[NL80211_BAND_2GHZ].ht_mcs[2], + mask->control[NL80211_BAND_2GHZ].ht_mcs[3]); + + /* Find the requested MCS index */ + for (int i = 0; i < 4; i++) { + if (mask->control[NL80211_BAND_2GHZ].ht_mcs[i]) { + for (int j = 0; j < 8; j++) { + if (mask->control[NL80211_BAND_2GHZ].ht_mcs[i] & (1 << j)) { + mcs_index = i * 8 + j; + pr_info("vwifi: Requested MCS index %d\n", mcs_index); + break; + } + } + if (mcs_index != -1) + break; + } + } + + if (mcs_index == -1) { + pr_err("vwifi: No valid MCS index found\n"); + return -EINVAL; + } + + if (mcs_index != 7 && mcs_index != 15 && mcs_index != 23 && + mcs_index != 31) { + pr_err("vwifi: Unsupported MCS index %d\n", mcs_index); + return -EINVAL; + } + + vif->manual_mcs = mcs_index; + vif->manual_mcs_set = true; + pr_info("vwifi: Set manual MCS %d for dev %s\n", mcs_index, dev->name); + + return 0; +} /* Structure of functions for FullMAC 80211 drivers. Functions implemented * along with fields/flags in the wiphy structure represent driver features. @@ -2175,6 +2299,7 @@ static struct cfg80211_ops vwifi_cfg_ops = { .get_tx_power = vwifi_get_tx_power, .join_ibss = vwifi_join_ibss, .leave_ibss = vwifi_leave_ibss, + .set_bitrate_mask = vwifi_set_bitrate_mask, }; /* Macro for defining 2GHZ channel array */ @@ -2191,6 +2316,7 @@ static struct cfg80211_ops vwifi_cfg_ops = { .center_freq = 5000 + (5 * (channel)), \ } + /* Macro for defining rate table */ #define RATE_ENT(_rate, _hw_value) \ { \ @@ -2198,7 +2324,7 @@ static struct cfg80211_ops vwifi_cfg_ops = { } /* Array of "supported" channels in 2GHz band. It is required for wiphy. */ -static const struct ieee80211_channel vwifi_supported_channels_2ghz[] = { +static struct ieee80211_channel vwifi_supported_channels_2ghz[] = { CHAN_2GHZ(1, 2412), CHAN_2GHZ(2, 2417), CHAN_2GHZ(3, 2422), CHAN_2GHZ(4, 2427), CHAN_2GHZ(5, 2432), CHAN_2GHZ(6, 2437), CHAN_2GHZ(7, 2442), CHAN_2GHZ(8, 2447), CHAN_2GHZ(9, 2452), @@ -2221,16 +2347,35 @@ static const struct ieee80211_channel vwifi_supported_channels_5ghz[] = { /* Array of supported rates, required to support those next rates * for 2GHz and 5GHz band. */ -static const struct ieee80211_rate vwifi_supported_rates[] = { +static struct ieee80211_rate vwifi_supported_rates[] = { RATE_ENT(10, 0x1), RATE_ENT(20, 0x2), RATE_ENT(55, 0x4), RATE_ENT(110, 0x8), RATE_ENT(60, 0x10), RATE_ENT(90, 0x20), RATE_ENT(120, 0x40), RATE_ENT(180, 0x80), RATE_ENT(240, 0x100), RATE_ENT(360, 0x200), RATE_ENT(480, 0x400), RATE_ENT(540, 0x800), }; -/* Describes supported band of 2GHz. */ -static struct ieee80211_supported_band nf_band_2ghz; - +static struct ieee80211_supported_band nf_band_2ghz = { + .band = NL80211_BAND_2GHZ, + .channels = vwifi_supported_channels_2ghz, + .n_channels = ARRAY_SIZE(vwifi_supported_channels_2ghz), + .bitrates = vwifi_supported_rates, + .n_bitrates = ARRAY_SIZE(vwifi_supported_rates), + .ht_cap = + { + .ht_supported = true, + .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_GRN_FLD | + IEEE80211_HT_CAP_MAX_AMSDU | + IEEE80211_HT_CAP_SUP_WIDTH_20_40, + .mcs = + { + .rx_mask = {0xff, 0xff, 0xff, 0xff}, /* MCS 0-31 */ + .rx_highest = cpu_to_le16(300), + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, + }, + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, + }, +}; /* Describes supported band of 5GHz. */ static struct ieee80211_supported_band nf_band_5ghz;