{"id":28000626,"url":"https://github.com/sysprog21/vwifi","last_synced_at":"2025-05-08T23:53:55.049Z","repository":{"id":37079783,"uuid":"402490561","full_name":"sysprog21/vwifi","owner":"sysprog21","description":"A virtual wireless device driver for Linux","archived":false,"fork":false,"pushed_at":"2025-05-03T11:31:18.000Z","size":784,"stargazers_count":225,"open_issues_count":6,"forks_count":43,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-05-08T23:53:49.774Z","etag":null,"topics":["cfg80211","linux","linux-drivers","mac80211","networking","nl80211","wifi-network","wireless-driver"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sysprog21.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-02T16:31:39.000Z","updated_at":"2025-04-23T17:44:15.000Z","dependencies_parsed_at":"2024-02-22T08:23:52.393Z","dependency_job_id":"977f68fb-1209-4980-b0e2-8d9c8d21afc2","html_url":"https://github.com/sysprog21/vwifi","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysprog21%2Fvwifi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysprog21%2Fvwifi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysprog21%2Fvwifi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysprog21%2Fvwifi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sysprog21","download_url":"https://codeload.github.com/sysprog21/vwifi/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253166486,"owners_count":21864471,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cfg80211","linux","linux-drivers","mac80211","networking","nl80211","wifi-network","wireless-driver"],"created_at":"2025-05-08T23:53:54.470Z","updated_at":"2025-05-08T23:53:55.036Z","avatar_url":"https://github.com/sysprog21.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# vwifi: A Simple Virtual Wireless Driver for Linux\n\n`vwifi` implements a minimal interface to provide essential functionalities,\nsuch as scanning for dummy Wi-Fi networks, establishing connections, and\ndisconnecting from them.\n\nIt is built upon the [cfg80211 subsystem](https://www.kernel.org/doc/html/latest/driver-api/80211/cfg80211.html),\nwhich collaborates with FullMAC drivers. Currently, `vwifi` supports both\nStation Mode and Host AP Mode and is equipped with robust WPA/WPA2 security\nfeatures. This enables users to configure a wireless environment using `vwifi`,\n`hostapd` (in HostAP mode interface), and `wpa_supplicant` (in station mode interface).\n\nMoreover, when running on hypervisors like QEMU, `vwifi` functions as a virtio-net\ndriver, allowing for inter-guest communication.\n\n## Prerequisite\n\nThe following packages must be installed before building `vwifi`.\n\nTo compile the kernel driver successfully, the package versions of the currently used kernel,\nkernel-devel, and kernel-headers need to be matched. Run the following command to install the required kernel headers:\n```shell\n$ sudo apt install linux-headers-$(uname -r)\n```\n\nSince `vwifi` relies on the Linux wireless (IEEE-802.11) subsystem, [iw](https://wireless.wiki.kernel.org/en/users/documentation/iw) is necessary for retrieving more information and configuring.\nInstall it using the following command:\n```shell\n$ sudo apt install iw\n```\n\nIf running the test script (scripts/verify.sh), Python 3, hostapd, and some additional packages are necessary.\n```shell\n$ sudo apt install python3 python3-pip hostapd\n$ pip3 install numpy matplotlib\n```\n\n## Testing environment (non-virtio)\nTo test the network environment effectively, we utilize **Linux network namespaces**. These namespaces isolate network environments from the host system, providing distinct instances of network stacks with independent routes, firewall rules, and network devices.\n\nWithout network namespaces, virtual interfaces created within the same namespace use the loopback device for packet transmission between them, as the kernel recognizes them as residing on the same host.\n\nIn our testing setup, all interfaces created by `vwifi` are placed within an isolated network namespace. This approach ensures that each virtual interface operates independently, facilitating comprehensive testing of networking functionalities without interference from the host's network configuration.\n\nBelow, we will conduct two separate tests: Infrastructure BSS and Independent BSS.\n### Infrastructure BSS\n\u003cp align=\"center\"\u003e\u003cimg src=\"assets/vwifi.png\" alt=\"logo image\" width=60%\u003e\u003c/p\u003e\n\nThe testing environment consists of **one AP and two STAs**.\n\nThe testing environment operates in IEEE 802.11 infrastructure BSS, which imposes a constraint: **STAs cannot directly communicate with each other**.\nWhen an STA wants to communicate with other devices, it must send packets to the AP.\nThe AP then performs the following actions based on the packet type:\n1. Unicast: If the packet is intended for another STA, the AP forwards it directly to the destination STA without passing it to the protocol stack.\n   If the packet is intended for the AP itself, it is passed to the protocol stack.\n2. Broadcast: The AP forwards the packet to all other STAs in the network, except for the source STA, and then passes it to the protocol stack.\n3. Multicast: The AP treats multicast packets the same way as broadcast packets.\n\n### Independent BSS\n\u003cp align=\"center\"\u003e\u003cimg src=\"assets/ibss.png\" alt=\"logo image\" width=75%\u003e\u003c/p\u003e\n\nThe testing environment consists of **two IBSS devices**.\n\nThe testing environment operates in IEEE 802.11 independent BSS. IBSS devices can communicate with any device in the same IBSS network **without the need to establish a connection beforehand**. However, devices in different IBSS networks cannot communicate with each other.\n## Build and Run (non-virtio)\n\nTo build the kernel module, execute the following command:\n```shell\n$ make\n```\n\nLoad the cfg80211 kernel module by running the following command:\n```shell\n$ sudo modprobe cfg80211\n```\n\nInsert the `vwifi` driver.\nThis will create three interfaces (the \"station\" parameter can be modified according to preference):\n```shell\n$ sudo insmod vwifi.ko station=5\n```\n\nPlease note that interfaces can only be created in station mode during the initialization phase.\nHowever, they can be switched to Host AP mode later using hostapd.\n\n### Checking Network Interfaces\n\nTo check the network interfaces, run the following command:\n```shell\n$ ip link\n```\n\nThere should be entries starting with `vw0`, `vw1`, `vw2`, `vw3`, and `vw4`, which correspond to the interfaces created by `vwifi`.\n\nTo view the available wireless interfaces, execute the following command:\n```shell\n$ sudo iw dev\n```\n\nYou should see something similar to the following output:\n```\nphy#5\n\tInterface vw4\n\t\tifindex 7\n\t\twdev 0x500000001\n\t\taddr 00:76:77:34:00:00\n\t\ttype managed\n\t\ttxpower 0.00 dBm\nphy#4\n\tInterface vw3\n\t\tifindex 6\n\t\twdev 0x400000001\n\t\taddr 00:76:77:33:00:00\n\t\ttype managed\n\t\ttxpower 0.00 dBm\nphy#3\n\tInterface vw2\n\t\tifindex 5\n\t\twdev 0x300000001\n\t\taddr 00:76:77:32:00:00\n\t\ttype managed\n\t\ttxpower 0.00 dBm\nphy#2\n\tInterface vw1\n\t\tifindex 4\n\t\twdev 0x200000001\n\t\taddr 00:76:77:31:00:00\n\t\ttype managed\n\t\ttxpower 0.00 dBm\nphy#1\n\tInterface vw0\n\t\tifindex 3\n\t\twdev 0x100000001\n\t\taddr 00:76:77:30:00:00\n\t\ttype managed\n\t\ttxpower 0.00 dBm\n```\n\nAs observed, each interface has its own phy (`struct wiphy`), allowing them to be placed into separate network namespaces.\n\n### Dumping Wireless Information\n\nTo obtain wireless information, execute the following command:\n```shell\n$ sudo iw list\n```\n\nReference output:\n```\nWiphy vw_phy4\n(... omit)\nWiphy vw_phy3\n(... omit)\nWiphy vw_phy2\n(... omit)\nWiphy vw_phy1\n(... omit)\nWiphy vw_phy0\n\twiphy index: 0\n\tmax # scan SSIDs: 69\n\tmax scan IEs length: 0 bytes\n\tmax # sched scan SSIDs: 0\n\tmax # match sets: 0\n\tRetry short limit: 7\n\tRetry long limit: 4\n\tCoverage class: 0 (up to 0m)\n\tSupported Ciphers:\n\t\t* WEP40 (00-0f-ac:1)\n\t\t* WEP104 (00-0f-ac:5)\n\t\t* TKIP (00-0f-ac:2)\n\t\t* CCMP-128 (00-0f-ac:4)\n\tAvailable Antennas: TX 0 RX 0\n\tSupported interface modes:\n\t\t * managed\n\t\t * AP\n\tBand 1:\n\t\tBitrates (non-HT):\n\t\t\t* 1.0 Mbps\n\t\t\t* 2.0 Mbps\n\t\t\t* 5.5 Mbps\n\t\t\t* 11.0 Mbps\n\t\t\t* 6.0 Mbps\n\t\t\t* 9.0 Mbps\n\t\t\t* 12.0 Mbps\n\t\t\t* 18.0 Mbps\n\t\t\t* 24.0 Mbps\n\t\t\t* 36.0 Mbps\n\t\t\t* 48.0 Mbps\n\t\t\t* 54.0 Mbps\n\t\tFrequencies:\n\t\t\t* 2412 MHz [1] (20.0 dBm)\n\t\t\t* 2417 MHz [2] (20.0 dBm)\n\t\t\t* 2422 MHz [3] (20.0 dBm)\n\t\t\t* 2427 MHz [4] (20.0 dBm)\n\t\t\t* 2432 MHz [5] (20.0 dBm)\n\t\t\t* 2437 MHz [6] (20.0 dBm)\n\t\t\t* 2442 MHz [7] (20.0 dBm)\n\t\t\t* 2447 MHz [8] (20.0 dBm)\n\t\t\t* 2452 MHz [9] (20.0 dBm)\n\t\t\t* 2457 MHz [10] (20.0 dBm)\n\t\t\t* 2462 MHz [11] (20.0 dBm)\n\t\t\t* 2467 MHz [12] (20.0 dBm) (no IR)\n\t\t\t* 2472 MHz [13] (20.0 dBm) (no IR)\n\t\t\t* 2484 MHz [14] (20.0 dBm) (no IR)\n\tSupported commands:\n\t\t * set_interface\n\t\t * new_key\n\t\t * start_ap\n\t\t * set_wiphy_netns\n\t\t * set_channel\n\t\t * connect\n\t\t * disconnect\n\tsoftware interface modes (can always be added):\n\tinterface combinations are not supported\n\tDevice supports scan flush.\n\tmax # scan plans: 1\n\tmax scan plan interval: -1\n\tmax scan plan iterations: 0\n\tSupported extended features:\n```\n\nYou can see the supported operating modes, supported ciphers, channels, bitrates, and supported commands in the output.\n\nThe \"managed mode\" in the Supported interface modes is identical to station mode.\n\n### Creating Network Namespaces\nNext, create three network namespaces using the following commands:\n```shell\n$ sudo ip netns add ns0\n$ sudo ip netns add ns1\n$ sudo ip netns add ns2\n````\n\nFind the `wiphy` name for the three interfaces.\nThe index number for the `wiphy` name postfix might be different each time.\nPlease use the following command for the ease of memorizing different index number everytime.\n```shell\n$ vw0_phy=$(sudo iw dev vw0 info | grep wiphy | awk '{print $2}')\n$ vw0_phy=$(sudo iw list | grep \"wiphy index: $vw0_phy\" -B 1 | grep Wiphy | awk '{print $2}')\n$ vw1_phy=$(sudo iw dev vw1 info | grep wiphy | awk '{print $2}')\n$ vw1_phy=$(sudo iw list | grep \"wiphy index: $vw1_phy\" -B 1 | grep Wiphy | awk '{print $2}')\n$ vw2_phy=$(sudo iw dev vw2 info | grep wiphy | awk '{print $2}')\n$ vw2_phy=$(sudo iw list | grep \"wiphy index: $vw2_phy\" -B 1 | grep Wiphy | awk '{print $2}')\n```\n\nCheck whether the name of each `wiphy` is the same as the name listing under the command `sudo iw list`\n```shell\n$ echo $vw0_phy\nvw_phy0\n$ echo $vw1_phy\nvw_phy1\n$ echo $vw2_phy\nvw_phy2\n```\n\nAssign the three interfaces to separate network namespaces.\nPlease note that the `wiphy` is placed within the network namespace, and the interface associated with that wiphy will be contained within it.\n```shell\n$ sudo iw phy vw_phy0 set netns name ns0\n$ sudo iw phy vw_phy1 set netns name ns1\n$ sudo iw phy vw_phy2 set netns name ns2\n```\n\n### Assigning IP Addresses to Each Interface\n\nNow, assign an IP address to both interfaces using the following commands:\n```shell\n$ sudo ip netns exec ns0 ip addr add 10.0.0.1/24 dev vw0\n$ sudo ip netns exec ns1 ip addr add 10.0.0.2/24 dev vw1\n$ sudo ip netns exec ns2 ip addr add 10.0.0.3/24 dev vw2\n```\n\n### Running hostapd on the HostAP Mode Interface\nPrepare the following script `hostapd.conf` (you can modify the script based on your needs):\n```\ninterface=vw0\ndriver=nl80211\ndebug=1\nctrl_interface=/var/run/hostapd\nctrl_interface_group=wheel\nchannel=6\nssid=test\nwpa=2\nwpa_passphrase=12345678\nwpa_key_mgmt=WPA-PSK\nwpa_pairwise=CCMP\n```\n\nRun `hostapd` on the interface `vw0`:\n```shell\t\n$ sudo ip netns exec ns0 hostapd -i vw0 -B scripts/hostapd.conf\n```\n\n### Running `wpa_supplicant` on the Station Mode Interfaces\nPrepare the following script `wpa_supplicant.conf` (you can modify the script based on your needs):\n```shell\nnetwork={\n    ssid=\"test\"\n    psk=\"12345678\"\n}\n```\n\nThen run the `wpa_supplicant` on the interface `ns1` and `ns2`:\n```shell\n$ sudo ip netns exec ns1 \\\n       wpa_supplicant -i vw1 -B -c scripts/wpa_supplicant.conf\n$ sudo ip netns exec ns2 \\\n      wpa_supplicant -i vw2 -B -c scripts/wpa_supplicant.conf \n```\n\n### Validating the Connection\nTo validate the connection, use the following command:\n```shell\n$ sudo ip netns exec ns1 iw dev vw1 link\n```\n\nThe output might seem like this:\n```\nConnected to 00:6f:77:6c:30:00 (on vw1)\n\tSSID: test\n\tfreq: 2437\n\tRX: 282 bytes (2 packets)\n\tTX: 248 bytes (2 packets)\n\tsignal: -84 dBm\n```\n\nIt shows that `vw1` has connected to the BSS with BSSID `00:6f:77:6c:30:00`, which is the MAC address of `vw0`.\n\nYou may also check the connection of `vw2` by slightly changing the command above.\n\nOn the other hand, we can validate all the stations connected to `vw0` by the following commands:\n```shell\nsudo ip netns exec ns0 iw dev vw0 station dump\n```\n\nThe output may seem like this:\n```\nStation 00:6f:77:6c:31:00 (on vw0)\n\tinactive time:\t5588 ms\n\trx bytes:\t5366\n\trx packets:\t65\n\ttx bytes:\t1772\n\ttx packets:\t18\n\ttx failed:\t74\n\tsignal:  \t-57 dBm\n\tcurrent time:\t1689679337171 ms\nStation 00:6f:77:6c:32:00 (on vw0)\n\tinactive time:\t5588 ms\n\trx bytes:\t5366\n\trx packets:\t65\n\ttx bytes:\t1772\n\ttx packets:\t18\n\ttx failed:\t74\n\tsignal:  \t-57 dBm\n\tcurrent time:\t1689679337171 ms\n```\n\n### Transmission/Receivement test\nFinally, we can do the ping test:\n1. To perform a ping test between two STAs (`vw1` and `vw2`), use the following command:\n```shell\n$ sudo ip netns exec ns1 ping -c 4 10.0.0.3\n```\n\nYou should see output similar to the following:\n```\nPING 10.0.0.3 (10.0.0.3) 56(84) bytes of data.\n64 bytes from 10.0.0.3: icmp_seq=1 ttl=64 time=0.188 ms\n64 bytes from 10.0.0.3: icmp_seq=2 ttl=64 time=0.147 ms\n64 bytes from 10.0.0.3: icmp_seq=3 ttl=64 time=0.082 ms\n64 bytes from 10.0.0.3: icmp_seq=4 ttl=64 time=0.136 ms\n\n--- 10.0.0.3 ping statistics ---\n4 packets transmitted, 4 received, 0% packet loss, time 3036ms\nrtt min/avg/max/mdev = 0.082/0.138/0.188/0.037 ms\n```\n\n2. To perform a ping test between the AP (`vw0`) and a STA (`vw2`), execute the following command:\n```shell\n$ sudo ip netns exec ns2 ping -c 4 10.0.0.1\n```\n\nYou should see output similar to the following:\n```\nPING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.\n64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.342 ms\n64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.054 ms\n64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.106 ms\n64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=0.063 ms\n\n--- 10.0.0.1 ping statistics ---\n4 packets transmitted, 4 received, 0% packet loss, time 3058ms\nrtt min/avg/max/mdev = 0.054/0.141/0.342/0.117 ms\n```\n### IBSS mode\n\n#### Creating Network Namespaces\nCreate three network namespaces using the following commands:\n```shell\n$ sudo ip netns add ns3\n$ sudo ip netns add ns4\n```\nFind the `wiphy` name for the two interfaces.\nThe index number for the `wiphy` name postfix might be different each time.\nPlease use the following command for the ease of memorizing different index number everytime.\n```shell\n$ vw3_phy=$(sudo iw dev vw3 info | grep wiphy | awk '{print $2}')\n$ vw3_phy=$(sudo iw list | grep \"wiphy index: $vw3_phy\" -B 1 | grep Wiphy | awk '{print $2}')\n$ vw4_phy=$(sudo iw dev vw4 info | grep wiphy | awk '{print $2}')\n$ vw4_phy=$(sudo iw list | grep \"wiphy index: $vw4_phy\" -B 1 | grep Wiphy | awk '{print $2}')\n```\nCheck whether the name of each `wiphy` is the same as the name listing under the command `sudo iw list`\n```shell\n$ echo $vw3_phy\nvw_phy3\n$ echo $vw4_phy\nvw_phy4\n```\nAssign the two interfaces to separate network namespaces.\nPlease note that the `wiphy` is placed within the network namespace, and the interface associated with that wiphy will be contained within it.\n```shell\n$ sudo iw phy vw_phy3 set netns name ns3\n$ sudo iw phy vw_phy4 set netns name ns4\n```\n#### Assigning IP Addresses to Each Interface\n\nNow, assign an IP address to both interfaces using the following commands:\n```shell\n$ sudo ip netns exec ns3 ip addr add 10.0.0.4/24 dev vw3\n$ sudo ip netns exec ns4 ip addr add 10.0.0.5/24 dev vw4\n```\nThere are two methods to configure an IBSS network: manual configuration or using WPA.\n#### Option1 : Manual configuration\n##### Switch to IBSS mode\nSwitch device to IBSS mode using the following command : \n\n***iw dev [interface] set type ibss***\n\nThe following commands switch `vw3` and `vw4` to IBSS mode. \n```shell\n$ sudo ip netns exec ns3 iw dev vw3 set type ibss\n$ sudo ip netns exec ns4 iw dev vw4 set type ibss\n```\nCheck the information of `vw3`.\n```shell\n$ sudo ip netns exec ns3 iw dev vw3 info\n```\nYou should see output similar to the following:\n```\nInterface vw3\n\tifindex 6\n\twdev 0x400000001\n\taddr 00:76:77:33:00:00\n\ttype IBSS\n\twiphy 4\n\ttxpower 0.00 dBm\n```\n##### Join IBSS network\n```shell\n$ sudo ip netns exec ns3 ip link set vw3 up\n$ sudo ip netns exec ns4 ip link set vw4 up\n```\nUsers can join a specific IBSS cell and configure additional settings using the command :\n\n***iw dev [interface] ibss join [SSID] [freq in MHz] [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz] [fixed-freq] [fixed-bssid] [beacon-interval \u003cTU\u003e] [basic-rates \u003crate in Mbps,rate2,…\u003e] [mcast-rate \u003crate in Mbps\u003e] [key d:0:abcde]*** \n\nIf the IBSS cell does not already exist, it will be created.\n\nThe following command makes `vw3` and `vw4` join the same IBSS cell with the SSID `ibss1` and specifies the frequency as 2412 MHz:\n```shell\n$ sudo ip netns exec ns3 iw dev vw3 ibss join ibss1 2412 NOHT fixed-freq 00:76:77:33:00:00 beacon-interval 200\n$ sudo ip netns exec ns4 iw dev vw4 ibss join ibss1 2412 NOHT fixed-freq 00:76:77:33:00:00 beacon-interval 200\n```\nCheck the information of `vw3`.\n```shell\n$ sudo ip netns exec ns3 iw dev vw3 info\n```\nYou should see output similar to the following:\n```\nInterface vw3\n\tifindex 6\n\twdev 0x400000001\n\taddr 00:76:77:33:00:00\n\tssid ibss1\n\ttype IBSS\n\twiphy 4\n\ttxpower 0.00 dBm\n```\n#### Option2 : Using WPA\n```shell\n$ sudo ip netns exec ns3 ip link set vw3 up\n$ sudo ip netns exec ns4 ip link set vw4 up\n```\nPrepare the following script `wpa_supplicant_ibss.conf` (you can modify the script based on your needs):\n```shell\nnetwork={\n    ssid=\"ibss1\"\n    mode=1\n    frequency=2412\n    key_mgmt=WPA-PSK\n    proto=RSN\n    pairwise=CCMP\n    group=CCMP\n    psk=\"12345678\"\n}\n```\nUsing the command **wpa_supplicant**, configure `vw3` and `vw4` to join `ibss1`.\n```shell\n$ sudo ip netns exec ns3 wpa_supplicant -i vw3 -B -c scripts/wpa_supplicant_ibss.conf\n$ sudo ip netns exec ns4 wpa_supplicant -i vw4 -B -c scripts/wpa_supplicant_ibss.conf\n```\nCheck the information of `vw3`.\n```shell\n$ sudo ip netns exec ns3 iw dev vw3 info\n```\nYou should see output similar to the following:\n```\nInterface vw3\n\tifindex 6\n\twdev 0x400000001\n\taddr 00:76:77:33:00:00\n\tssid ibss1\n\ttype IBSS\n\twiphy 4\n\ttxpower 0.00 dBm\n```\n#### Transmission/Receivement test\nTo perform a ping test between two IBSS devices (`vw3` and `vw4`) in the same ibss cell (`ibss1`), use the following command:\n```shell\n$ sudo ip netns exec ns3 ping -c 1 10.0.0.5\n```\nYou should see output similar to the following:\n```\nPING 10.0.0.5 (10.0.0.5) 56(84) bytes of data.\n64 bytes from 10.0.0.5: icmp_seq=1 ttl=64 time=0.093 ms\n\n--- 10.0.0.5 ping statistics ---\n1 packets transmitted, 1 received, 0% packet loss, time 0ms\nrtt min/avg/max/mdev = 0.093/0.093/0.093/0.000 ms\n```\n#### Leave IBSS network\nTo leave the current IBSS cell, use ***iw dev [interface] ibss leave***. \n\nThe following command makes `vw3` and `vw4` leave `ibss1`:\n```shell\n$ sudo ip netns exec ns3 iw dev vw3 ibss leave\n$ sudo ip netns exec ns4 iw dev vw4 ibss leave\n```\nCheck the information of `vw3`.\n```shell\n$ sudo ip netns exec ns3 iw dev vw3 info\n```\nYou should see output similar to the following:\n```\nInterface vw3\n\tifindex 6\n\twdev 0x400000001\n\taddr 00:76:77:33:00:00\n\ttype IBSS\n\twiphy 4\n\ttxpower 0.00 dBm\n```\n\n### vwifi-tool\nA userspace tool which supports more user-specific utilization for vwifi.\nAiming to provide more flexibility and customization for users of vwifi.\nCurrently supporting feature:\n* display the status of vwifi driver\n* Use netlink socket to communicate with vwifi driver allowing user to configure user-specific deny list\n\n#### Status checking\nWe can use `vwifi-tool` to check the status of vwifi driver by executing the following command:\n```\n$ ./vwifi-tool\n```\nIf vwifi is loaded into kernel, you should see the following output:\n```\nvwifi status : live\n```\nOtherwise, vwifi isn't loaded into kernel yet, the output will be:\n```\nvwifi status : not loaded\n```\n\n#### Denylist test\nvwifi also supports denylist ability to allow some interfaces to deny packets from certain interfaces.\nWe can use `vwifi-tool` to set or unset denylist for vwifi, multiple options are explained as below\n* `-d` : specify the destination interface for a denylist pair\n* `-s` : specify the source interface for a denylist pair\n* `-c` : `1` means to unset the denylist in vwifi, default as `0`\n\nSet the denylist pair using vwifi-tool like the following\n```\n$ ./vwifi-tool -d vw2 -s vw1\n```\nYou should see the following output, including your denylist which will be sent to vwifi\n```\nvwifi status : live\ndenylist:\nvw2 denys vw1\nConfiguring denylist for vwifi...\nMessage from vwifi: vwifi has received your denylist\n```\nThen you can try to do the ping test again\n```\n$ sudo ip netns exec ns1 ping -c 4 10.0.0.3\n```\nYou should see the following output:\n```\nPING 10.0.0.3 (10.0.0.3) 56(84) bytes of data.\n\n--- 10.0.0.3 ping statistics ---\n4 packets transmitted, 0 received, 100% packet loss, time 3053ms\n```\nYou can adjust the content of your denylist and load it into vwifi anytime.\n\nIf you want to unset the denylist in vwifi, simply add the option `-c` with vwifi-tool\n```\n$ ./vwifi-tool -c\n```\nYou'll see the following output\n```\nvwifi status : live\nUnset denylist for vwifi...\nConfiguring denylist for vwifi...\nMessage from vwifi: vwifi has received your denylist\n```\n## Testing environment (virtio)\nBelow is our testing environment with virtio feature:\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"assets/virtio.png\" alt=\"vwifi virtio image\" width=60%\u003e\u003c/p\u003e\n\n`vwifi` utilizes the virtio-net device, the Linux tap device, and the Linux\nbridge device to enable inter-guest communication.\n\nIn our testing environment, on the host side, we create three tap devices and\none bridge device. Then, we attach each tap device to the bridge device. We also\ncreate three VMs using QEMU, configuring each with a virtio-net device and\nspecifying that each virtio-net device connects to a corresponding tap device on\nthe host.\n\nIn VM1, the network interface created by `vwifi` operates in HostAP mode, with\nthe user program hostapd running on top of it. In VM2 and VM3, we have STA mode\ninterfaces with `wpa_supplicant` running on top of them.\n\n## Build and Run (virtio)\nBelow describes how to build a minimal workable VM environment.\n### Build Linux kernel\nDownload Linux kernel source from [kernel.org](https://kernel.org/). \n\nEnter the top directory of the Linux kernel source and use the following command to generate the configuration file:\n```shell\n$ make menuconfig\n```\nThe default kernel cofiguration will work for our testing environment, so just click `save` and we get `.config` on the top directory.\n\nBefore building the kernel, please ensure that all the needed packges or libraries have been installed in your machine.\n\nThen Build the kernel:\n```shell\n$ make -j\u003cnum threads\u003e\n```\n\nOnce we have finished building the kernel, the `bzImage` will be in the `arch/\u003carchitecture\u003e/boot/` directory. For x86 machine, that is `arch/x86/boot/bzImage`.\n\n### Build `vwifi`\nAssume directory vwifi is cloned from [vwifi](https://github.com/sysprog21/vwifi), and enter the top directory.\n\n`vwifi` let the `$(KDIR)` in `Makefile` point to the default kernel source on the host, but the kernel version of the host may differ from the one for the VMs, so we need to replace it to point to the kernel source we previously built for the VMs:\n```shell\nKDIR = \u003clinux kernel top directory for VMs\u003e\n```\n\nSave the change and build `vwifi`:\n```shell\n$ make\n```\n\nOn success, we expect that `vwifi.ko` will show in the top directory of `vwifi`.\n\nThe cfg80211 API and net device API in the kernel have changed along with the new kernel version, and forgive us for not testing for all of them.\n### Build Rootfs by Buildroot\nWe use `buildroot` to build our rootfs, you can either choose your desired tool for building rootfs.\n\nGet the `builtroot` from [https://buildroot.org](https://buildroot.org).\n\nEnter the top directory of the `buildroot` source and use the following command to generate the first-phase configuration file:\n```shell\n$ make qemu_x86_64_defconfig\n```\n\nThe `qemu_x86_64_defconfig` configuration will not fit the testing environment, so we need to further configure it:\n```shell\n$ make menuconfig\n```\n\nWe need a filesystem overlay for putting our `vwifi` kernel module and some user program's configuration file into the VM, so choose a place for the filesystem overlay (we recommand creating an empty directory for it).\n\nAlso, we need network applications like `iw`, `hostapd` and `wpa_supplicant`.\n```\nSystem configuration ---\u003e Run a getty (login prompt) after boot ---\u003e TTY port ---\u003e ttyS0\nSystem configuration ---\u003e Root filesystem overlay directories ---\u003e \u003cthe place you wnat\u003e\nKernel ---\u003e Linux Kernel ---\u003e no\nTarget packages ---\u003e Networking applications ---\u003e hostapd\nTarget packages ---\u003e Networking applications ---\u003e iw\nTarget packages ---\u003e Networking applications ---\u003e wpa_supplicant\nFilesystem images ---\u003e ext2/3/4 root filesystem\n```\n\nAfter finishing the configuration, we can put the needed kernel modules and configuration files into the filesystem overlay directory:\n```shell\ncp \u003clinux-top-dir\u003e/net/wireless/cfg80211.ko \\\n\u003cvwifi-top-dir\u003e/vwifi.ko \\\n\u003cvwifi-top-dir\u003e/scripts/hostapd.conf \\\n\u003cvwifi-top-dir\u003e/scripts/wpa_supplicant.conf \\\n\u003coverlay-dir\u003e\n```\n\nThen start building rootfs:\n```shell\n$ make\n```\nThis may take a long time, please be patient.\n\nThe output image will be `output/images/rootfs.ext2`. We need three images for three VMs, so we simply copy this file into three:\n```shell\n$ cp output/images/rootfs.ext2 output/images/rootfs2.ext2\n$ cp output/images/rootfs.ext2 output/images/rootfs3.ext2\n```\n\n### Setup Host Network Device\nWe need three `tap` devices and each of them must be attached to a `bridge` device. Please note, creating `tap` and `bridge` devices needs privilege permission.\n\nCreating three `tap` devices:\n```shell\n$ sudo ip tuntap add mode tap tap0\n$ sudo ip tuntap add mode tap tap1\n$ sudo ip tuntap add mode tap tap2\n```\n\nCreating `bridge` device:\n```shell\n$ sudo ip link add name br0 type bridge\n```\n\nAttach three `tap` devices on `bridge` device:\n```shell\n$ sudo ip link set tap0 master br0\n$ sudo ip link set tap1 master br0\n$ sudo ip link set tap2 master br0\n```\n\n### Start VM with Qemu\nOnce we have our kernel image and rootfs, we can start running `Qemu`:\n\n```shell\n$ sudo qemu-system-x86_64 -kernel bzImage \\\n-drive file=\u003cbuildroot rootfs image\u003e -nographic \\\n-append \"console=ttyS0\" \\\n-append root=/dev/sda \\\n-netdev tap,id=\u003cany name\u003e,ifname=\u003chost tap device\u003e \\\n-device virtio-net-pci,netdev=\u003cthe name in id=\u003e,mac=\u003cMAC address\u003e,mrg_rxbuf=off \\\n-serial mon:stdio\n```\n\nYou need to run the command above three times, please ensure the `buildroot` rootfs image, `tap` device and MAC address in every VM must be different. Also, ensure that the `mrg_rxbuf=off` has been specified.\n\n### Needed Steps in Every VM\n#### Raondom Number Generator\n`hostapd` and `wpa_supplicant` need the random number generator `/dev/random` for generating the random number used in a 4-way handshake. However, for some reason (which may be related to IRQ), accessing `/dev/random` may be not available or even not possible. And we found that `/dev/urandom` is always available, so we use a soft link to let the  `/dev/random` link to `/dev/urandom`:\n```shell\nmv /dev/random /dev/random.orig\nln -s /dev/urandom /dev/random\n```\n#### Loading Kernel Modules\n`vwifi` depends on `cfg80211.ko`, so firstly we load the `cfg80211.ko`:\n```shell\ninsmod cfg80211.ko\n```\n\nThen we can load our `vwifi.ko`. Note that for now, we only allow single network interface in `vwifi` when it's running on virtio:\n```shell\ninsmod vwifi.ko station=1\n```\n\n#### Setting Network Interface\nStart the network interface:\n```shell\nip link set vw0 up\n```\nAnd assign an IP address. Note that, we should assign different IP addresses (but the same subnet) for every network interface in the three VMs:\n```shell\nip addr add \u003cIP address/netmask\u003e dev vw0\n```\n### Start `hostapd` and `wpa_supplicant`\nIn our testing environment, the HostAP mode interface is in VM1, so running `hostapd` on VM1:\n```shell\nhostapd -i vw0 -B hostapd.conf\n```\nAnd running `wpa_supplicant` on the other two VMs:\n```shell\nwpa_supplicant -i vw0 -B -c wpa_supplicant.conf\n```\n\nFor now, the two STA mode interfaces in VM1 and VM2 should have been connected to the AP mode interface in VM0. \n\nFor validating the connection for the STA mode network interface, use the following command:\n```shell\niw dev vw0 link\n```\n### Ping Test\nIn VM1, we can ping the network interfaces in VM2 and VM3:\n```\nping \u003cvm2 interface's ip address\u003e\n```\n\n```\nping \u003cvm3 interface's ip address\u003e\n```\nLikewise, VM2 and VM3 can ping the other VMs as well.\n\n### Optional: Monitoring Wireless Device\n\nIf desired, you can use wireless device monitoring applications such as [wavemon](https://github.com/uoaerg/wavemon) to observe signal and noise levels,\npacket statistics, device configuration, and network parameters of `vwifi`.\n```shell\n$ sudo apt install wavemon\n```\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"assets/wavemon.png\" alt=\"logo image\" width=40%\u003e\u003c/p\u003e\n\n## License\n\n`vwifi` is released under the MIT license. Use of this source code is governed\nby a MIT-style license that can be found in the LICENSE file.\n\n## Reference\n\n* [mac80211_hwsim](https://www.kernel.org/doc/html/latest/networking/mac80211_hwsim/mac80211_hwsim.html): software simulator of 802.11 radio(s) for mac80211\n* [Emulating WLAN in Linux - part I: the 802.11 stack](https://linuxembedded.fr/2020/05/emulating-wlan-in-linux-part-i-the-80211-stack)\n* [Emulating WLAN in Linux - part II: mac80211_hwsim](https://linuxembedded.fr/2021/01/emulating-wlan-in-linux-part-ii-mac80211hwsim)\n* [virt_wifi](https://github.com/torvalds/linux/blob/master/drivers/net/wireless/virtual/virt_wifi.c): a complete virtual wireless driver that can be used as a wrapper around Ethernet.\n* [vwifi](https://github.com/Raizo62/vwifi): simulate Wi-Fi (802.11) between Linux Virtual Machines.\n* [virtio-overview](https://www.redhat.com/en/blog/virtio-devices-and-drivers-overview-headjack-and-phone): an virtio overview.\n* [virtio: How data travels](https://www.redhat.com/en/blog/virtqueues-and-virtio-ring-how-data-travels): explain the virtqueue and virtio ring.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsysprog21%2Fvwifi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsysprog21%2Fvwifi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsysprog21%2Fvwifi/lists"}