Skip to content

Commit

Permalink
Implement customized naming for wiphy
Browse files Browse the repository at this point in the history
The default phy%d naming for wiphy in linux kernel depends on the value
 of a static variable wiphy_counter. Since they never attempts to
 decrease the value of wiphy_counter even a wiphy is unregistered or
 freed, this behavior ensures the naming and indexing for wiphy will
 be absolutely unique.

However, the kernel might have other projects also utilize wiphy
structure, which will cause some confusion of wiphy's index and naming
when using `struct wiphy`. We implement a custom-made name "vw_phy%d"
for wiphy in our project, in order to seperate the naming and indexing
for `struct wiphy` in our project.

As for the troublesome behavior causing by the never-decreasing index of
wiphy structure as decribed in #54, we suggest to make some changes when
doing manual testing by finding the wiphy index of the interface first,
and use the index to query the actual wiphy's name for the interface as
describe in the changes of README.md.

Close #54
  • Loading branch information
vax-r committed Jan 28, 2024
1 parent ff5f9e4 commit 4c45815
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 13 deletions.
34 changes: 28 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,11 @@ $ sudo iw list

Reference output:
```
Wiphy phy2
Wiphy vw_phy2
(... omit)
Wiphy phy1
Wiphy vw_phy1
(... omit)
Wiphy phy0
Wiphy vw_phy0
wiphy index: 0
max # scan SSIDs: 69
max scan IEs length: 0 bytes
Expand Down Expand Up @@ -205,12 +205,34 @@ $ sudo ip netns add ns1
$ sudo ip netns add ns2
````

Find the `wiphy` name for the three interfaces.
The index number for the `wiphy` name postfix might be different each time.
Please use the following command for the ease of memorizing different index number everytime.
```shell
$ vw0_phy=$(sudo iw dev vw0 info | grep wiphy | awk '{print $2}')
$ vw0_phy=$(sudo iw list | grep "wiphy index: $vw0_phy" -B 1 | grep Wiphy | awk '{print $2}')
$ vw1_phy=$(sudo iw dev vw1 info | grep wiphy | awk '{print $2}')
$ vw1_phy=$(sudo iw list | grep "wiphy index: $vw1_phy" -B 1 | grep Wiphy | awk '{print $2}')
$ vw2_phy=$(sudo iw dev vw2 info | grep wiphy | awk '{print $2}')
$ vw2_phy=$(sudo iw list | grep "wiphy index: $vw2_phy" -B 1 | grep Wiphy | awk '{print $2}')
```

Check whether the name of each `wiphy` is the same as the name listing under the command `sudo iw list`
```shell
$ echo $vw0_phy
vw_phy0
$ echo $vw1_phy
vw_phy1
$ echo $vw2_phy
vw_phy2
```

Assign the three interfaces to separate network namespaces.
Please note that the `wiphy` is placed within the network namespace, and the interface associated with that wiphy will be contained within it.
```shell
$ sudo iw phy phy0 set netns name ns0
$ sudo iw phy phy1 set netns name ns1
$ sudo iw phy phy2 set netns name ns2
$ sudo iw phy $vw_phy0 set netns name ns0
$ sudo iw phy $vw_phy1 set netns name ns1
$ sudo iw phy $vw_phy2 set netns name ns2
```

### Assigning IP Addresses to Each Interface
Expand Down
12 changes: 6 additions & 6 deletions scripts/verify.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ if [ $final_ret -eq 0 ]; then

# get phy number of each interface
sudo iw dev > device.log
vw0_phy=$(cat device.log | grep -B 1 vw0 | grep phy)
vw0_phy=${vw0_phy/\#/}
vw1_phy=$(cat device.log | grep -B 1 vw1 | grep phy)
vw1_phy=${vw1_phy/\#/}
vw2_phy=$(cat device.log | grep -B 1 vw2 | grep phy)
vw2_phy=${vw2_phy/\#/}
vw0_phy=$(sudo iw dev vw0 info | grep wiphy | awk '{print $2}')
vw0_phy=$(sudo iw list | grep "wiphy index: $vw0_phy" -B 1 | grep Wiphy | awk '{print $2}')
vw1_phy=$(sudo iw dev vw1 info | grep wiphy | awk '{print $2}')
vw1_phy=$(sudo iw list | grep "wiphy index: $vw1_phy" -B 1 | grep Wiphy | awk '{print $2}')
vw2_phy=$(sudo iw dev vw2 info | grep wiphy | awk '{print $2}')
vw2_phy=$(sudo iw list | grep "wiphy index: $vw2_phy" -B 1 | grep Wiphy | awk '{print $2}')

# create network namespaces for each phy (interface)
sudo ip netns add ns0
Expand Down
42 changes: 41 additions & 1 deletion vwifi.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ MODULE_DESCRIPTION("virtual cfg80211 driver");
#define NAME_PREFIX "vw"
#define NDEV_NAME NAME_PREFIX "%d"

#define VWIFI_WIPHY_NAME_LEN 12
#define VWIFI_WIPHY_PREFIX "vw_phy"

#define DOT11_MGMT_HDR_LEN 24 /* d11 management header len */
#define DOT11_BCN_PRB_FIXED_LEN 12 /* beacon/probe fixed length */

Expand Down Expand Up @@ -71,6 +74,11 @@ static DEFINE_SPINLOCK(vif_list_lock);
/* SME stands for "station management entity" */
enum sme_state { SME_DISCONNECTED, SME_CONNECTING, SME_CONNECTED };

/* Each virtual interface contains a wiphy, vwifi_wiphy_counter is responsible
* for recording the number of wiphy in vwifi.
*/
static atomic_t vwifi_wiphy_counter = ATOMIC_INIT(0);

/* Virtual interface pointed to by netdev_priv(). Fields in the structure are
* interface-dependent. Every interface has its own vwifi_vif, regardless of the
* interface mode (STA, AP, Ad-hoc...).
Expand Down Expand Up @@ -1898,13 +1906,45 @@ static struct wiphy *vwifi_cfg80211_add(void)
struct wiphy *wiphy = NULL;
enum nl80211_band band;

/* Inorder to customize vwifi's wiphy name, we use vwifi_wiphy_counter to
* keep track of the number of wiphy in vwifi, and use vwifi_wiphy_idx to
* retreive the value of vwifi_wiphy_counter.
*/
int vwifi_wiphy_idx = atomic_inc_return(&vwifi_wiphy_counter);

/* atomic_inc_return makes it start at 1, make it start at 0 */
vwifi_wiphy_idx--;
if (unlikely(vwifi_wiphy_idx < 0)) {
atomic_dec(&vwifi_wiphy_counter);
return NULL;
}

/* allocate wiphy context. It is possible just to use wiphy_new().
* wiphy should represent physical FullMAC wireless device. We need
* to implement add_virtual_intf() from cfg80211_ops for adding
* interface(s) on top of a wiphy.
* NULL means use the default phy%d naming.
* vwifi_wiphy_name is the custom-made vw_phy%d naming we use for
* wiphy in vwifi.
*/
wiphy = wiphy_new_nm(&vwifi_cfg_ops, 0, NULL);

/* Reference:
* Linux Kernel Tag : v6.7.1
* The default phy%d naming for wiphy in linux kernel depends on the value
* of a static variable wiphy_counter. The value of wiphy_counter will never
* decrease even if we unregister the wiphy. This behavior ensures that the
* naming and indexing for `struct wiphy` will be absolutely unique.
* However, the kernel might have other modules or projects also utilizing
* `struct wiphy`, which will cause some confusion of wiphy's index and
* naming when using the default naming scheme. We implement a custom-made
* name "vw_phy%d" for wiphy in vwifi device driver, in order to seperate
* the naming and indexing for `struct wiphy` in vwifi.
*/
char vwifi_wiphy_name[VWIFI_WIPHY_NAME_LEN] = {0};
snprintf(vwifi_wiphy_name, VWIFI_WIPHY_NAME_LEN, "%s%d", VWIFI_WIPHY_PREFIX,
vwifi_wiphy_idx);

wiphy = wiphy_new_nm(&vwifi_cfg_ops, 0, vwifi_wiphy_name);
if (!wiphy) {
pr_info("couldn't allocate wiphy device\n");
return NULL;
Expand Down

0 comments on commit 4c45815

Please sign in to comment.