diff --git a/README.md b/README.md index 5e12551..90371c1 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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 diff --git a/scripts/common.sh b/scripts/common.sh index 702cec0..5b38d07 100644 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -65,3 +65,10 @@ function stop_hostapd() { sudo kill -9 $(pidof hostapd) > /dev/null return 0 } + +function get_wiphy_name() { + local interface_name=$1 + local wiphy_name=$(sudo iw dev $interface_name info | grep wiphy | awk '{print $2}') + wiphy_name=$(sudo iw list | grep "wiphy index: $wiphy_name" -B 1 | grep Wiphy | awk '{print $2}') + echo $wiphy_name +} \ No newline at end of file diff --git a/scripts/verify.sh b/scripts/verify.sh index cc6fddf..af8b481 100755 --- a/scripts/verify.sh +++ b/scripts/verify.sh @@ -26,12 +26,9 @@ 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=$(get_wiphy_name vw0) + vw1_phy=$(get_wiphy_name vw1) + vw2_phy=$(get_wiphy_name vw2) # create network namespaces for each phy (interface) sudo ip netns add ns0 diff --git a/vwifi.c b/vwifi.c index 4ce5221..7aa2003 100644 --- a/vwifi.c +++ b/vwifi.c @@ -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 */ @@ -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...). @@ -1898,13 +1906,45 @@ static struct wiphy *vwifi_cfg80211_add(void) struct wiphy *wiphy = NULL; enum nl80211_band band; + /* In order 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: + * https://elixir.bootlin.com/linux/latest/source/net/wireless/core.c#L450 + * 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;