diff --git a/drivers/net/wireless/virt_wifi.c b/drivers/net/wireless/virt_wifi.c index 946246c6270d..6a7b53ff18d7 100644 --- a/drivers/net/wireless/virt_wifi.c +++ b/drivers/net/wireless/virt_wifi.c @@ -18,6 +18,7 @@ #include #include #include +#include static struct wiphy *common_wiphy; @@ -25,6 +26,7 @@ struct virt_wifi_wiphy_priv { struct delayed_work scan_result; struct cfg80211_scan_request *scan_request; bool being_deleted; + struct virt_wifi_network_simulation *network_simulation; }; static struct ieee80211_channel channel_2ghz = { @@ -153,6 +155,9 @@ static int virt_wifi_scan(struct wiphy *wiphy, priv->scan_request = request; schedule_delayed_work(&priv->scan_result, HZ * 2); + if (priv->network_simulation && + priv->network_simulation->notify_scan_trigger) + priv->network_simulation->notify_scan_trigger(wiphy, request); return 0; } @@ -183,6 +188,12 @@ static void virt_wifi_scan_result(struct work_struct *work) DBM_TO_MBM(-50), GFP_KERNEL); cfg80211_put_bss(wiphy, informed_bss); + if(priv->network_simulation && + priv->network_simulation->generate_virt_scan_result) { + if(priv->network_simulation->generate_virt_scan_result(wiphy)) + wiphy_err(wiphy, "Fail to generater the simulated scan result.\n"); + } + /* Schedules work which acquires and releases the rtnl lock. */ cfg80211_scan_done(priv->scan_request, &scan_info); priv->scan_request = NULL; @@ -370,6 +381,8 @@ static struct wiphy *virt_wifi_make_wiphy(void) priv = wiphy_priv(wiphy); priv->being_deleted = false; priv->scan_request = NULL; + priv->network_simulation = NULL; + INIT_DELAYED_WORK(&priv->scan_result, virt_wifi_scan_result); err = wiphy_register(wiphy); @@ -385,7 +398,6 @@ static struct wiphy *virt_wifi_make_wiphy(void) static void virt_wifi_destroy_wiphy(struct wiphy *wiphy) { struct virt_wifi_wiphy_priv *priv; - WARN(!wiphy, "%s called with null wiphy", __func__); if (!wiphy) return; @@ -419,8 +431,13 @@ static netdev_tx_t virt_wifi_start_xmit(struct sk_buff *skb, static int virt_wifi_net_device_open(struct net_device *dev) { struct virt_wifi_netdev_priv *priv = netdev_priv(dev); - + struct virt_wifi_wiphy_priv *w_priv; priv->is_up = true; + w_priv = wiphy_priv(dev->ieee80211_ptr->wiphy); + if(w_priv->network_simulation && + w_priv->network_simulation->notify_device_open) + w_priv->network_simulation->notify_device_open(dev); + return 0; } @@ -440,6 +457,10 @@ static int virt_wifi_net_device_stop(struct net_device *dev) virt_wifi_cancel_connect(dev); netif_carrier_off(dev); + if (w_priv->network_simulation && + w_priv->network_simulation->notify_device_stop) + w_priv->network_simulation->notify_device_stop(dev); + return 0; } @@ -624,6 +645,27 @@ static void __exit virt_wifi_cleanup_module(void) virt_wifi_destroy_wiphy(common_wiphy); } +int virt_wifi_register_network_simulation + (struct virt_wifi_network_simulation *ops) +{ + struct virt_wifi_wiphy_priv *priv = wiphy_priv(common_wiphy); + if (priv->network_simulation) + return -EEXIST; + priv->network_simulation = ops; + return 0; +} +EXPORT_SYMBOL(virt_wifi_register_network_simulation); + +int virt_wifi_unregister_network_simulation(void) +{ + struct virt_wifi_wiphy_priv *priv = wiphy_priv(common_wiphy); + if(!priv->network_simulation) + return -ENODATA; + priv->network_simulation = NULL; + return 0; +} +EXPORT_SYMBOL(virt_wifi_unregister_network_simulation); + module_init(virt_wifi_init_module); module_exit(virt_wifi_cleanup_module); diff --git a/include/net/virt_wifi.h b/include/net/virt_wifi.h new file mode 100644 index 000000000000..343e73968d41 --- /dev/null +++ b/include/net/virt_wifi.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* include/net/virt_wifi.h + * + * Define the extension interface for the network data simulation + * + * Copyright (C) 2019 Google, Inc. + * + * Author: lesl@google.com + */ +#ifndef __VIRT_WIFI_H +#define __VIRT_WIFI_H + +struct virt_wifi_network_simulation { + void (*notify_device_open)(struct net_device *dev); + void (*notify_device_stop)(struct net_device *dev); + void (*notify_scan_trigger)(struct wiphy *wiphy, + struct cfg80211_scan_request *request); + int (*generate_virt_scan_result)(struct wiphy *wiphy); +}; + +int virt_wifi_register_network_simulation( + struct virt_wifi_network_simulation *ops); +int virt_wifi_unregister_network_simulation(void); +#endif +