OpenWrt hwsim fixes for emulated AP testing
Fixes for running vwifi between an OpenWrt DUT VM and a Linux test runner with mac80211_hwsim radios: 1. pmaddr fallback (ckernelwifi.cc): ethtool GPERMADDR fails on OpenWrt hwsim VIFs (wlanc0/wlanc1). handle_new_winet_notification() and handle_init_winet_notification() now fall back to nl80211 MAC when get_pmaddr() returns false, instead of silently dropping the VIF. 2. hwsim MAC 0x40 bit fix (cwirelessdevice.cc): Set locally-administered bit on machwsim in constructor and setMachwsim() to match the kernel's hwsim rhashtable key format. Fixes frame delivery to radios created via netlink. 3. VIF name regex fix (cwirelessdevice.cc): wlan regex changed from "wlan[0-9]*" to "wlan[a-z]?[0-9]*" to match OpenWrt captive portal VIFs (wlanc0, wlanc1). 4. Frame deduplication (ckernelwifi.cc): Multiple BSS VIFs (wlan0, wlan0-1) share the same PHY permanent MAC. Without dedup, frames are delivered N times to the same radio, causing duplicate auth/assoc and breaking WPA handshakes. 5. Frequency routing (ckernelwifi.cc, ckernelwifi.h): Track each radio's channel from TX frames. Skip radios not tuned to the frame's frequency in process_messages (local delivery). Disabled for recv_from_server (kernel handles RX freq filtering). 6. freq=0 passthrough for recv_from_server (ckernelwifi.cc): Pass freq=0 to send_cloned_frame_msg so the kernel skips its HWSIM_ATTR_FREQ check. Prevents drops from TCP timing races between scan dwell changes and frame delivery. 7. TCP_NODELAY (csocketclientitcp.cc, csocketserverfunctionitcp.cc): Disable Nagle's algorithm for lower latency frame relay. 8. writev for atomic sends (cwifi.cc): Replace two separate send() calls (power + data) with a single writev() to prevent interleaving with concurrent writers. 9. Netlink buffer increase (ckernelwifi.cc): nl_socket_set_buffer_size 16MB to prevent frame drops under load. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
92df7a383a
commit
4d144cd2f4
+147
-5
@@ -36,6 +36,31 @@ CDynBuffer Buffer;
|
|||||||
/* allow calling non static function from static function */
|
/* allow calling non static function from static function */
|
||||||
ckernelwifi::CallFromStaticFunc * CKernelWifi::forward = nullptr ;
|
ckernelwifi::CallFromStaticFunc * CKernelWifi::forward = nullptr ;
|
||||||
|
|
||||||
|
/* Frequency routing: track each radio's channel from its TX frames */
|
||||||
|
void CKernelWifi::update_radio_freq(const struct ether_addr* mac, TFrequency freq) {
|
||||||
|
if (freq == 0) return;
|
||||||
|
for (int i = 0; i < _radio_freq_cache_size; i++) {
|
||||||
|
if (memcmp(&_radio_freq_cache[i].mac, mac, sizeof(struct ether_addr)) == 0) {
|
||||||
|
_radio_freq_cache[i].freq = freq;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_radio_freq_cache_size < MAX_RADIO_FREQ_CACHE) {
|
||||||
|
_radio_freq_cache[_radio_freq_cache_size].mac = *mac;
|
||||||
|
_radio_freq_cache[_radio_freq_cache_size].freq = freq;
|
||||||
|
_radio_freq_cache_size++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TFrequency CKernelWifi::get_radio_freq(const struct ether_addr* mac) const {
|
||||||
|
for (int i = 0; i < _radio_freq_cache_size; i++) {
|
||||||
|
if (memcmp(&_radio_freq_cache[i].mac, mac, sizeof(struct ether_addr)) == 0) {
|
||||||
|
return _radio_freq_cache[i].freq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0; /* unknown — deliver frame (conservative fallback) */
|
||||||
|
}
|
||||||
|
|
||||||
void CKernelWifi::cout_mac_address(struct ether_addr *src)
|
void CKernelWifi::cout_mac_address(struct ether_addr *src)
|
||||||
{
|
{
|
||||||
char addr[18];
|
char addr[18];
|
||||||
@@ -210,15 +235,48 @@ int CKernelWifi::process_messages(struct nl_msg *msg)
|
|||||||
else
|
else
|
||||||
freq = 0;
|
freq = 0;
|
||||||
|
|
||||||
|
/* Update frequency cache for this transmitting radio */
|
||||||
|
update_radio_freq(&macsrchwsim, freq);
|
||||||
|
{
|
||||||
|
static int _tx_dbg = 0;
|
||||||
|
if (_tx_dbg < 10) {
|
||||||
|
char _txm[18];
|
||||||
|
sprintf(_txm, "%02X:%02X:%02X:%02X:%02X:%02X", macsrchwsim.ether_addr_octet[0], macsrchwsim.ether_addr_octet[1], macsrchwsim.ether_addr_octet[2], macsrchwsim.ether_addr_octet[3], macsrchwsim.ether_addr_octet[4], macsrchwsim.ether_addr_octet[5]);
|
||||||
|
std::cerr << "TX process_messages #" << _tx_dbg << " src_mac=" << _txm << " freq=" << freq << std::endl;
|
||||||
|
_tx_dbg++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int rate_idx = 7; // number of attempts
|
int rate_idx = 7; // number of attempts
|
||||||
|
|
||||||
const auto& inets = _list_winterfaces.list_devices();
|
const auto& inets = _list_winterfaces.list_devices();
|
||||||
|
/* Deduplicate by permanent hwsim MAC (see recv_from_server comment) */
|
||||||
|
struct ether_addr sent_macs_local[16];
|
||||||
|
int n_sent_local = 0;
|
||||||
for (const auto& inet : inets)
|
for (const auto& inet : inets)
|
||||||
{
|
{
|
||||||
struct ether_addr macdsthwsim = inet.getMachwsim();
|
struct ether_addr macdsthwsim = inet.getMachwsim();
|
||||||
if( memcmp(&macsrchwsim,&macdsthwsim,sizeof(struct ether_addr)) ) // if( macsrchwsim != macdsthwsim )
|
if( memcmp(&macsrchwsim,&macdsthwsim,sizeof(struct ether_addr)) ) {
|
||||||
|
bool dup = false;
|
||||||
|
for (int i = 0; i < n_sent_local; i++) {
|
||||||
|
if (memcmp(&sent_macs_local[i], &macdsthwsim, sizeof(struct ether_addr)) == 0) {
|
||||||
|
dup = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!dup) {
|
||||||
|
if (n_sent_local < 16)
|
||||||
|
sent_macs_local[n_sent_local++] = macdsthwsim;
|
||||||
|
/* Frequency routing: skip radios not on this channel.
|
||||||
|
* freq=0 in frame: deliver to all (no freq info).
|
||||||
|
* target_freq=0: radio not tuned yet, skip it. */
|
||||||
|
TFrequency target_freq = get_radio_freq(&macdsthwsim);
|
||||||
|
if (freq != 0 && target_freq != 0 && target_freq != freq)
|
||||||
|
continue;
|
||||||
send_cloned_frame_msg(&macdsthwsim, data, data_len, rate_idx, power, freq);
|
send_cloned_frame_msg(&macdsthwsim, data, data_len, rate_idx, power, freq);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
delete &inets;
|
delete &inets;
|
||||||
// <------------------------
|
// <------------------------
|
||||||
|
|
||||||
@@ -317,6 +375,10 @@ int CKernelWifi::init_netlink_first(void)
|
|||||||
perror("setsockopt");
|
perror("setsockopt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Increase netlink receive buffer to 4MB to prevent frame drops under load.
|
||||||
|
* Must be after genl_connect() which assigns the socket fd. */
|
||||||
|
nl_socket_set_buffer_size(_netlink_socket, 16 * 1024 * 1024, 0);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,6 +460,10 @@ int CKernelWifi::init_netlink(void)
|
|||||||
perror("setsockopt");
|
perror("setsockopt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Increase netlink receive buffer to 4MB to prevent frame drops under load.
|
||||||
|
* Must be after genl_connect() which assigns the socket fd. */
|
||||||
|
nl_socket_set_buffer_size(_netlink_socket, 16 * 1024 * 1024, 0);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,11 +508,18 @@ int CKernelWifi::send_cloned_frame_msg(struct ether_addr *dst, char *data, int d
|
|||||||
|
|
||||||
// nl_send_auto_complete(_netlink_socket, msg);
|
// nl_send_auto_complete(_netlink_socket, msg);
|
||||||
|
|
||||||
if (nl_send_auto(_netlink_socket, msg) < 0)
|
int _nl_rc = nl_send_auto(_netlink_socket, msg);
|
||||||
|
static int _send_count = 0;
|
||||||
|
_send_count++;
|
||||||
|
if (_nl_rc < 0)
|
||||||
{
|
{
|
||||||
|
std::cerr << "nl_send_auto FAILED: rc=" << _nl_rc << " count=" << _send_count << std::endl;
|
||||||
nlmsg_free(msg);
|
nlmsg_free(msg);
|
||||||
return 0 ;
|
return 0 ;
|
||||||
}
|
}
|
||||||
|
if (_send_count <= 10 || _send_count % 100 == 0) {
|
||||||
|
std::cerr << "nl_send_auto OK: rc=" << _nl_rc << " count=" << _send_count << " freq=" << freq << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
nlmsg_free(msg);
|
nlmsg_free(msg);
|
||||||
|
|
||||||
@@ -455,6 +528,21 @@ int CKernelWifi::send_cloned_frame_msg(struct ether_addr *dst, char *data, int d
|
|||||||
|
|
||||||
void CKernelWifi::recv_from_server(){
|
void CKernelWifi::recv_from_server(){
|
||||||
|
|
||||||
|
static int _dbg_count = 0;
|
||||||
|
if (_dbg_count < 5 || _dbg_count % 1000 == 0) {
|
||||||
|
const auto& _dbg_inets = _list_winterfaces.list_devices();
|
||||||
|
std::cerr << "recv_from_server #" << _dbg_count << " list_size=" << _dbg_inets.size();
|
||||||
|
for (const auto& _di : _dbg_inets) {
|
||||||
|
char _dm[18];
|
||||||
|
const struct ether_addr _dpm = _di.getMachwsim();
|
||||||
|
sprintf(_dm, "%02X:%02X:%02X:%02X:%02X:%02X", _dpm.ether_addr_octet[0], _dpm.ether_addr_octet[1], _dpm.ether_addr_octet[2], _dpm.ether_addr_octet[3], _dpm.ether_addr_octet[4], _dpm.ether_addr_octet[5]);
|
||||||
|
std::cerr << " [" << _di.getName() << "=" << _dm << "]";
|
||||||
|
}
|
||||||
|
std::cerr << std::endl;
|
||||||
|
delete &_dbg_inets;
|
||||||
|
}
|
||||||
|
_dbg_count++;
|
||||||
|
|
||||||
if ( ! is_connected_to_server())
|
if ( ! is_connected_to_server())
|
||||||
return ;
|
return ;
|
||||||
|
|
||||||
@@ -535,11 +623,52 @@ void CKernelWifi::recv_from_server(){
|
|||||||
|
|
||||||
const auto& inets = _list_winterfaces.list_devices();
|
const auto& inets = _list_winterfaces.list_devices();
|
||||||
|
|
||||||
|
/* Deduplicate by permanent hwsim MAC: multiple BSS interfaces
|
||||||
|
* (wlan0, wlan0-1, wlan0-2) share the same PHY permanent MAC.
|
||||||
|
* Without dedup, each frame is delivered N times to the same radio,
|
||||||
|
* causing duplicate auth/assoc and breaking WPA handshakes. */
|
||||||
|
struct ether_addr sent_macs[16];
|
||||||
|
int n_sent = 0;
|
||||||
|
|
||||||
for (const auto& inet : inets)
|
for (const auto& inet : inets)
|
||||||
{
|
{
|
||||||
struct ether_addr macdsthwsim = inet.getMachwsim();
|
struct ether_addr macdsthwsim = inet.getMachwsim();
|
||||||
|
|
||||||
send_cloned_frame_msg(&macdsthwsim, data, data_len, rate_idx, signal, freq);
|
bool dup = false;
|
||||||
|
for (int i = 0; i < n_sent; i++) {
|
||||||
|
if (memcmp(&sent_macs[i], &macdsthwsim, sizeof(struct ether_addr)) == 0) {
|
||||||
|
dup = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dup)
|
||||||
|
continue;
|
||||||
|
if (n_sent < 16)
|
||||||
|
sent_macs[n_sent++] = macdsthwsim;
|
||||||
|
|
||||||
|
/* Frequency routing: skip radios not on this channel.
|
||||||
|
* freq=0 in frame: deliver to all (no freq info).
|
||||||
|
* target_freq=0: radio freq unknown, deliver anyway. */
|
||||||
|
TFrequency target_freq = get_radio_freq(&macdsthwsim);
|
||||||
|
if (_dbg_count < 20) {
|
||||||
|
char _fm[18];
|
||||||
|
sprintf(_fm, "%02X:%02X:%02X:%02X:%02X:%02X", macdsthwsim.ether_addr_octet[0], macdsthwsim.ether_addr_octet[1], macdsthwsim.ether_addr_octet[2], macdsthwsim.ether_addr_octet[3], macdsthwsim.ether_addr_octet[4], macdsthwsim.ether_addr_octet[5]);
|
||||||
|
std::cerr << " freq_route: mac=" << _fm << " frame_freq=" << freq << " target_freq=" << target_freq << (((freq != 0 && target_freq != 0 && target_freq != freq) ? " SKIP" : " DELIVER")) << std::endl;
|
||||||
|
}
|
||||||
|
/* Frequency routing disabled for recv_from_server: kernel
|
||||||
|
* mac80211_hwsim handles RX frequency filtering internally.
|
||||||
|
* The userspace check races with scan dwell timing over TCP,
|
||||||
|
* causing 5GHz beacons to be dropped during client scans. */
|
||||||
|
// if (freq != 0 && target_freq != 0 && target_freq != freq)
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
/* Pass freq=0 so the kernel skips its own HWSIM_ATTR_FREQ
|
||||||
|
* check in hwsim_cloned_frame_received_nl. Without this,
|
||||||
|
* the kernel drops frames whose freq doesn't match the
|
||||||
|
* radio's current channel — which races with scan dwell
|
||||||
|
* timing over TCP. The kernel's mac80211 RX path handles
|
||||||
|
* frequency validation at a higher level. */
|
||||||
|
send_cloned_frame_msg(&macdsthwsim, data, data_len, rate_idx, signal, 0);
|
||||||
}
|
}
|
||||||
delete &inets;
|
delete &inets;
|
||||||
}
|
}
|
||||||
@@ -550,6 +679,9 @@ void CKernelWifi::monitor_hwsim_loop()
|
|||||||
|
|
||||||
sock = nl_socket_alloc();
|
sock = nl_socket_alloc();
|
||||||
genl_connect(sock);
|
genl_connect(sock);
|
||||||
|
/* Increase netlink receive buffer to 4MB to prevent frame drops under load.
|
||||||
|
* Must be after genl_connect() which assigns the socket fd. */
|
||||||
|
nl_socket_set_buffer_size(sock, 16 * 1024 * 1024, 0);
|
||||||
|
|
||||||
/* loop for waiting incoming msg from hwsim driver*/
|
/* loop for waiting incoming msg from hwsim driver*/
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -1008,8 +1140,13 @@ void CKernelWifi::handle_new_winet_notification(WirelessDevice wirelessdevice){
|
|||||||
|
|
||||||
//paddr.ether_addr_octet[0] |= 0x40 ;
|
//paddr.ether_addr_octet[0] |= 0x40 ;
|
||||||
wirelessdevice.setMachwsim(paddr);
|
wirelessdevice.setMachwsim(paddr);
|
||||||
_list_winterfaces.add_device(wirelessdevice);
|
} else {
|
||||||
|
/* Fallback: ethtool GPERMADDR fails on OpenWrt hwsim VIFs.
|
||||||
|
Use the nl80211 MAC (addresses[0]) — setMachwsim applies |=0x40
|
||||||
|
to derive addresses[1] for the hwsim rhashtable key. */
|
||||||
|
wirelessdevice.setMachwsim(wirelessdevice.getMacaddr());
|
||||||
}
|
}
|
||||||
|
_list_winterfaces.add_device(wirelessdevice);
|
||||||
|
|
||||||
//std::cout << __func__ << _list_winterfaces << std::endl ;
|
//std::cout << __func__ << _list_winterfaces << std::endl ;
|
||||||
|
|
||||||
@@ -1032,8 +1169,13 @@ void CKernelWifi::handle_init_winet_notification(WirelessDevice wirelessdevice){
|
|||||||
|
|
||||||
//paddr.ether_addr_octet[0] |= 0x40 ;
|
//paddr.ether_addr_octet[0] |= 0x40 ;
|
||||||
wirelessdevice.setMachwsim(paddr);
|
wirelessdevice.setMachwsim(paddr);
|
||||||
_list_winterfaces.add_device(wirelessdevice);
|
} else {
|
||||||
|
/* Fallback: ethtool GPERMADDR fails on OpenWrt hwsim VIFs.
|
||||||
|
Use the nl80211 MAC (addresses[0]) — setMachwsim applies |=0x40
|
||||||
|
to derive addresses[1] for the hwsim rhashtable key. */
|
||||||
|
wirelessdevice.setMachwsim(wirelessdevice.getMacaddr());
|
||||||
}
|
}
|
||||||
|
_list_winterfaces.add_device(wirelessdevice);
|
||||||
|
|
||||||
//std::cout << __func__ << _list_winterfaces << std::endl ;
|
//std::cout << __func__ << _list_winterfaces << std::endl ;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
|
||||||
#include "cdynbuffer.h"
|
#include "cdynbuffer.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
namespace ckernelwifi{
|
namespace ckernelwifi{
|
||||||
|
|
||||||
@@ -39,6 +40,22 @@ class CKernelWifi : public intthread::AsyncTask {
|
|||||||
|
|
||||||
WirelessDeviceList _list_winterfaces ;
|
WirelessDeviceList _list_winterfaces ;
|
||||||
|
|
||||||
|
/* Frequency routing: cache each radio's last-seen frequency.
|
||||||
|
* Updated from TX frames (HWSIM_ATTR_FREQ). Used to skip
|
||||||
|
* radios not tuned to the frame's frequency, eliminating
|
||||||
|
* the N-radio broadcast overhead. freq=0 means unknown
|
||||||
|
* (radio hasn't transmitted yet) — deliver as fallback. */
|
||||||
|
static constexpr int MAX_RADIO_FREQ_CACHE = 16;
|
||||||
|
struct RadioFreqEntry {
|
||||||
|
struct ether_addr mac;
|
||||||
|
TFrequency freq;
|
||||||
|
};
|
||||||
|
RadioFreqEntry _radio_freq_cache[MAX_RADIO_FREQ_CACHE] = {};
|
||||||
|
int _radio_freq_cache_size = 0;
|
||||||
|
|
||||||
|
void update_radio_freq(const struct ether_addr* mac, TFrequency freq);
|
||||||
|
TFrequency get_radio_freq(const struct ether_addr* mac) const;
|
||||||
|
|
||||||
/** pointer for netlink socket */
|
/** pointer for netlink socket */
|
||||||
struct nl_sock * _netlink_socket { nullptr };
|
struct nl_sock * _netlink_socket { nullptr };
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <fcntl.h> // open
|
#include <fcntl.h> // open
|
||||||
|
|
||||||
#include <arpa/inet.h> // INADDR_ANY
|
#include <arpa/inet.h> // INADDR_ANY
|
||||||
|
#include <netinet/tcp.h>
|
||||||
#include <unistd.h> // close
|
#include <unistd.h> // close
|
||||||
#include <assert.h> // assert
|
#include <assert.h> // assert
|
||||||
|
|
||||||
@@ -34,6 +35,9 @@ bool CSocketClientITCP::_Configure()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nodelay = 1;
|
||||||
|
setsockopt(Master, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <arpa/inet.h> // INADDR_ANY
|
#include <arpa/inet.h> // INADDR_ANY
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
|
||||||
#include "csocket.h" // SOCKET_ERROR
|
#include "csocket.h" // SOCKET_ERROR
|
||||||
#include "csocketserverfunctionitcp.h"
|
#include "csocketserverfunctionitcp.h"
|
||||||
@@ -91,5 +92,8 @@ TDescriptor CSocketServerFunctionITCP::_Accept(TDescriptor master, TCID& cid)
|
|||||||
|
|
||||||
cid=hash_ipaddr(&address);
|
cid=hash_ipaddr(&address);
|
||||||
|
|
||||||
|
int nodelay = 1;
|
||||||
|
setsockopt(new_socket, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay));
|
||||||
|
|
||||||
return new_socket;
|
return new_socket;
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-21
@@ -8,6 +8,7 @@
|
|||||||
#include "hwsim.h" // HWSIM_ATTR_FREQ
|
#include "hwsim.h" // HWSIM_ATTR_FREQ
|
||||||
#include <netlink/genl/genl.h> // genlmsg_parse
|
#include <netlink/genl/genl.h> // genlmsg_parse
|
||||||
|
|
||||||
|
#include <sys/uio.h> // writev
|
||||||
#include "cwifi.h"
|
#include "cwifi.h"
|
||||||
|
|
||||||
//#include "config.h"
|
//#include "config.h"
|
||||||
@@ -64,34 +65,36 @@ bool CWifi::PacketIsLost(TPower signalLevel)
|
|||||||
|
|
||||||
ssize_t CWifi::SendSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, const char* buffer, int sizeOfBuffer)
|
ssize_t CWifi::SendSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, const char* buffer, int sizeOfBuffer)
|
||||||
{
|
{
|
||||||
// cout<<"send power : "<<power<<endl;
|
struct iovec iov[2];
|
||||||
int val=socket->Send(descriptor, reinterpret_cast<const char*>(power), sizeof(TPower));
|
iov[0].iov_base = power;
|
||||||
if( val <= 0 )
|
iov[0].iov_len = sizeof(TPower);
|
||||||
return val;
|
iov[1].iov_base = const_cast<char*>(buffer);
|
||||||
|
iov[1].iov_len = sizeOfBuffer;
|
||||||
// std::cout<<"send big data of size : "<<sizeOfBuffer<<std::endl;
|
ssize_t total = sizeof(TPower) + sizeOfBuffer;
|
||||||
return socket->Send(descriptor, buffer, sizeOfBuffer);
|
ssize_t ret = writev(descriptor, iov, 2);
|
||||||
|
if (ret != total)
|
||||||
|
return SOCKET_ERROR;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t CWifi::RecvSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, CDynBuffer* buffer)
|
ssize_t CWifi::RecvSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, CDynBuffer* buffer)
|
||||||
{
|
{
|
||||||
int valread;
|
ssize_t n;
|
||||||
|
n=socket->Read(descriptor, (char*)power, sizeof(TPower));
|
||||||
// read the power
|
if( n == SOCKET_ERROR )
|
||||||
valread = socket->Read(descriptor, reinterpret_cast<char*>(power), sizeof(TPower));
|
|
||||||
if ( valread <= 0 )
|
|
||||||
return valread;
|
|
||||||
|
|
||||||
// read the signal
|
|
||||||
// "nlmsg_len" (type "uint32_t") is the first attribut of the "struct nlmsghdr" in "libnl3/netlink/netlink-kernel.h"
|
|
||||||
ssize_t sizeRead = socket->ReadEqualSize(descriptor, buffer, 0, sizeof(struct nlmsghdr));
|
|
||||||
if( sizeRead == SOCKET_ERROR )
|
|
||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
|
|
||||||
int sizeTotal=reinterpret_cast<struct nlmsghdr *>(buffer->GetBuffer())->nlmsg_len;
|
/* we read nlmsghdr to get the size of the message */
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
buffer->NeededSize(sizeof(struct nlmsghdr),false);
|
||||||
|
n=socket->ReadEqualSize(descriptor, buffer, 0, sizeof(struct nlmsghdr));
|
||||||
|
if( n == SOCKET_ERROR )
|
||||||
|
return SOCKET_ERROR;
|
||||||
|
nlh = (struct nlmsghdr *)buffer->GetBuffer();
|
||||||
|
int sizeTotal=nlh->nlmsg_len;
|
||||||
|
|
||||||
if( sizeTotal > MTU ) // to avoid that a error packet overfulls the memory
|
if( sizeTotal > MTU )
|
||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
|
|
||||||
return socket->ReadEqualSize(descriptor, buffer, sizeRead, sizeTotal);
|
return socket->ReadEqualSize(descriptor, buffer, sizeof(struct nlmsghdr), sizeTotal);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
const std::regex wlan("wlan[0-9]*");
|
const std::regex wlan("wlan[a-z]?[0-9]*");
|
||||||
|
|
||||||
WirelessDevice::WirelessDevice(){
|
WirelessDevice::WirelessDevice(){
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ WirelessDevice::~WirelessDevice(){
|
|||||||
|
|
||||||
WirelessDevice::WirelessDevice(const std::string & name,int index ,int iftype ,const struct ether_addr & macaddr,int txpower):_name(name),_index(index),_iftype(iftype), _txpower(txpower), _macaddr(macaddr), _machwsim(macaddr) {
|
WirelessDevice::WirelessDevice(const std::string & name,int index ,int iftype ,const struct ether_addr & macaddr,int txpower):_name(name),_index(index),_iftype(iftype), _txpower(txpower), _macaddr(macaddr), _machwsim(macaddr) {
|
||||||
|
|
||||||
// _machwsim.ether_addr_octet[0] |= 0x40 ;
|
_machwsim.ether_addr_octet[0] |= 0x40 ;
|
||||||
|
|
||||||
// std::memcpy(&_macaddr,&macaddr,ETH_ALEN);
|
// std::memcpy(&_macaddr,&macaddr,ETH_ALEN);
|
||||||
|
|
||||||
@@ -43,6 +43,7 @@ struct ether_addr WirelessDevice::getMacaddr() const {
|
|||||||
void WirelessDevice::setMachwsim(const struct ether_addr & machwsim) {
|
void WirelessDevice::setMachwsim(const struct ether_addr & machwsim) {
|
||||||
|
|
||||||
_machwsim = machwsim ;
|
_machwsim = machwsim ;
|
||||||
|
_machwsim.ether_addr_octet[0] |= 0x40 ;
|
||||||
// std::memcpy(&_macaddr,&macaddr,ETH_ALEN);
|
// std::memcpy(&_macaddr,&macaddr,ETH_ALEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user