You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This patch provides preliminary support for virtio-net, enabling
inter-guest communication with the correct settings.
To enable virtio support, we have made vwifi capable of recognizing
virtio-net devices by registering vwifi with the virtio driver and
providing the necessary probe/remove functions. Regarding virtqueues
(referred to as vq), we currently have one RX vq and one TX vq
(multi-queue support is not yet available):
- TX vq: Whenever a frame needs to be sent, we add an output buffer to
the TX vq and call virtqueue_kick() to transmit the data to the
virtio-net device.
- RX vq: Upon ndo_open(), we populate an input buffer into the RX vq and
replenish the input buffer with each RX interrupt.
It is important to note that when putting/getting buffers or kicking
buffers, we must hold the virtio spinlock to ensure that no other
operations occur on the vq simultaneously. Additionally, while acquiring
the spinlock, we should avoid calling dev_kfree_skb() (as it is not safe
in interrupt context) and restrict ourselves to using kmalloc() with
GFP_ATOMIC. We use spin_lock_irqsave() because the TX/RX completion
interrupt might be reentrant and could potentially lead to deadlocks.
As of now, vwifi does not support most of the virtio-net features. To
provide future support, our focus should initially be on implementing
multi-queue support and incorporating NAPI on the RX path.
In the context of vwifi management frames, originally, vwifi performed
management operations, such as cfg80211_ops->scan(), and handled the TX/RX
path using a 'shortcut' method. This entailed acquiring the network
interface structures and struct owl_vif by iterating through the vif
list and locating the one with the same MAC address. This approach was
feasible only when all interfaces resided on the same host.
To address the challenge of dealing with vwifi spread across multiple
machines, we have introduced the concept of "vwifi management frames."
Many of these management frame types draw inspiration from IEEE 802.11
management frames, with minor adjustments made due to the fact that we
are dealing with Ethernet frames. It is important to note that we
transmit these management frames with the Ethertype/length field set as
"length" (i.e., 802.3 frames). This allows us to distinguish them from
data frames (Ethernet II).
Additionally, it is crucial to ensure that multi-octet fields follow
a specific byte order so that data is consistently interpreted across
different machines. We employ a little-endian byte order, making it
possible for most machines to directly read the data. Multi-octet fields
should be of the __leX type, and the sender is responsible for calling
cpu_to_leX() on the data to be transmitted. This enables the receiver to
utilize leX_to_cpu() to access and store the data in its machine's byte
order.
For a more comprehensive description of all management frame types
(including how an STA handles frames from other BSS), please refer to the
comments in vwifi.c, located above the definition of enum
VWIFI_VIRTIO_PACKET_TYPE.
Signed-off-by: EN-WEI WU <[email protected]>
Copy file name to clipboardExpand all lines: README.md
+190-2
Original file line number
Diff line number
Diff line change
@@ -6,6 +6,8 @@ It is based on the [cfg80211 subsystem](https://www.kernel.org/doc/html/latest/d
6
6
which works together with FullMAC drivers.
7
7
Currently, vwifi supports both Station Mode and Host AP Mode, and is well-equipped with WPA/WPA2 security facilities. This enables users to set up a wireless environment using vwifi, hostapd (in HostAP mode interface), and wpa_supplicant (in station mode interface).
8
8
9
+
Furthermore, when running on hypervisors like Qemu, `vwifi` becomes a `virtio-net` driver and has the capability to do inter-guest communication. To test `vwifi` with the virtio feature, [click here](#Testing-environment-(virtio)) to jump to the virtio section below.
10
+
9
11
## Prerequisite
10
12
11
13
The following packages must be installed before building `vwifi`.
vwifi makes use of the `virtio-net` device, Linux tap device, and Linux bridge device to fulfill inter-guest communication.
348
+
In our testing environment, on the host side, we create three `tap` devices and one `bridge` device, then attach each `tap` device to the `bridge` device. And we create three VMs by `Qemu` with the `virtio-net` devices and specify that every `virtio-net` device connects to a `tap` device in the host.
349
+
In VM1, the network interface created by `vwifi` will be in HostAP mode, with the user program `hostapd` running on top of it.
350
+
In VM2 and VM3, we have an STA mode interface and `wpa_supplicant` running on top of it.
351
+
## Build and Run (virtio)
352
+
Below describes how to build a minimal workable VM environment.
353
+
### Build Linux kernel
354
+
Download Linux kernel source from [kernel.org](https://kernel.org/).
355
+
356
+
Enter the top directory of the Linux kernel source and use the following command to generate the configuration file:
357
+
```shell
358
+
make menuconfig
359
+
```
360
+
The default kernel cofiguration will work for our testing environment, so just click `save` and we get `.config` on the top directory.
361
+
362
+
Before building the kernel, please ensure that all the needed packges or libraries have been installed in your machine.
363
+
364
+
Then Build the kernel:
365
+
```
366
+
make -j<num threads>
367
+
```
368
+
369
+
Once we have finished building the kernel, the `bzImage` will be in the `arch/<architecture>/boot/` directory. For x86 machine, that is `arch/x86/boot/bzImage`.
370
+
371
+
### Build `vwifi`
372
+
Assume directory vwifi is cloned from [vwifi](https://github.com/sysprog21/vwifi), and enter the top directory.
373
+
374
+
`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:
375
+
```shell
376
+
KDIR = <linux kernel top directory for VMs>
377
+
```
378
+
379
+
Save the change and build `vwifi`:
380
+
```shell
381
+
make
382
+
```
383
+
384
+
On success, we expect that `vwifi.ko` will show in the top directory of `vwifi`.
385
+
386
+
The 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.
387
+
### Build Rootfs by Buildroot
388
+
We use `buildroot` to build our rootfs, you can either choose your desired tool for building rootfs.
389
+
390
+
Get the `builtroot` from [https://buildroot.org](https://buildroot.org).
391
+
392
+
Enter the top directory of the `buildroot` source and use the following command to generate the first-phase configuration file:
393
+
```shell
394
+
make qemu_x86_64_defconfig
395
+
```
396
+
397
+
The `qemu_x86_64_defconfig` configuration will not fit the testing environment, so we need to further configure it:
398
+
```shell
399
+
make menuconfig
400
+
```
401
+
402
+
We 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).
403
+
404
+
Also, we need network applications like `iw`, `hostapd` and `wpa_supplicant`.
405
+
```
406
+
System configuration ---> Run a getty (login prompt) after boot ---> TTY port ---> ttyS0
407
+
System configuration ---> Root filesystem overlay directories ---> <the place you wnat>
We 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.
437
+
438
+
Creating three `tap` devices:
439
+
```shell
440
+
sudo ip tuntap add mode tap tap0
441
+
sudo ip tuntap add mode tap tap1
442
+
sudo ip tuntap add mode tap tap2
443
+
```
444
+
445
+
Creating `bridge` device:
446
+
```shell
447
+
sudo ip link add name br0 type bridge
448
+
```
449
+
450
+
Attach three `tap` devices on `bridge` device:
451
+
```shell
452
+
sudo ip link set tap0 master br0
453
+
sudo ip link set tap1 master br0
454
+
sudo ip link set tap2 master br0
455
+
```
456
+
457
+
### Start VM with Qemu
458
+
Once we have our kernel image and rootfs, we can start running `Qemu`:
459
+
460
+
```shell
461
+
sudo qemu-system-x86_64 -kernel bzImage \
462
+
-drive file=<buildroot rootfs image> -nographic \
463
+
-append "console=ttyS0" \
464
+
-append root=/dev/sda \
465
+
-netdev tap,id=<any name>,ifname=<host tap device> \
466
+
-device virtio-net-pci,netdev=<the name in id=>,mac=<MAC address>,mrg_rxbuf=off \
467
+
-serial mon:stdio
468
+
```
469
+
470
+
You 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.
471
+
472
+
### Needed Steps in Every VM
473
+
#### Raondom Number Generator
474
+
`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`:
475
+
```shell
476
+
mv /dev/random /dev/random.orig
477
+
ln -s /dev/urandom /dev/random
478
+
```
479
+
#### Loading Kernel Modules
480
+
`vwifi` depends on `cfg80211.ko`, so firstly we load the `cfg80211.ko`:
481
+
```shell
482
+
insmod cfg80211.ko
483
+
```
484
+
485
+
Then we can load our `vwifi.ko`. Note that for now, we only allow single network interface in `vwifi` when it's running on virtio:
486
+
```shell
487
+
insmod vwifi.ko station=1
488
+
```
489
+
490
+
#### Setting Network Interface
491
+
Start the network interface:
492
+
```shell
493
+
ip link set owl0 up
494
+
```
495
+
And assign an IP address. Note that, we should assign different IP addresses (but the same subnet) for every network interface in the three VMs:
496
+
```shell
497
+
ip addr add <IP address/netmask> dev owl0
498
+
```
499
+
### Start `hostapd` and `wpa_supplicant`
500
+
In our testing environment, the HostAP mode interface is in VM1, so running `hostapd` on VM1:
501
+
```shell
502
+
hostapd -i owl0 -B hostapd.conf
503
+
```
504
+
And running `wpa_supplicant` on the other two VMs:
505
+
```shell
506
+
wpa_supplicant -i owl0 -B -c wpa_supplicant.conf
507
+
```
508
+
509
+
For now, the two STA mode interfaces in VM1 and VM2 should have been connected to the AP mode interface in VM0.
510
+
511
+
For validating the connection for the STA mode network interface, use the following command:
512
+
```shell
513
+
iw dev owl0 link
514
+
```
515
+
### Ping Test
516
+
In VM1, we can ping the network interfaces in VM2 and VM3:
517
+
```
518
+
ping <vm2 interface's ip address>
519
+
```
520
+
521
+
```
522
+
ping <vm3 interface's ip address>
523
+
```
524
+
Likewise, VM2 and VM3 can ping the other VMs as well.
525
+
340
526
### Optional: Monitoring Wireless Device
341
527
342
528
If desired, you can use wireless device monitoring applications such as [wavemon](https://github.com/uoaerg/wavemon) to observe signal and noise levels,
@@ -359,3 +545,5 @@ by a MIT-style license that can be found in the LICENSE file.
359
545
*[Emulating WLAN in Linux - part II: mac80211_hwsim](https://linuxembedded.fr/2021/01/emulating-wlan-in-linux-part-ii-mac80211hwsim)
360
546
*[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.
361
547
*[vwifi](https://github.com/Raizo62/vwifi): simulate Wi-Fi (802.11) between Linux Virtual Machines.
548
+
*[virtio-overview](https://www.redhat.com/en/blog/virtio-devices-and-drivers-overview-headjack-and-phone): an virtio overview.
549
+
*[virtio: How data travels](https://www.redhat.com/en/blog/virtqueues-and-virtio-ring-how-data-travels): explain the virtqueue and virtio ring.
0 commit comments