Skip to content

Commit 8cde8f0

Browse files
shemmingerdavem330
authored andcommitted
hv_netvsc: drop common code until callback model fixed
The callback model of handling network failover is not suitable in the current form. 1. It was merged without addressing all the review feedback. 2. It was merged without approval of any of the netvsc maintainers. 3. Design discussion on how to handle PV/VF fallback is still not complete. 4. IMHO the code model using callbacks is trying to make something common which isn't. Revert the netvsc specific changes for now. Does not impact ongoing development of failover model for virtio. Revisit this after a simpler library based failover kernel routines are extracted. This reverts commit 9c6ffba ("hv_netvsc: fix error return code in netvsc_probe()") and commit 1ff7807 ("netvsc: refactor notifier/event handling code to use the failover framework") Signed-off-by: Stephen Hemminger <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 01a1a17 commit 8cde8f0

File tree

3 files changed

+165
-62
lines changed

3 files changed

+165
-62
lines changed

drivers/net/hyperv/Kconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,5 @@ config HYPERV_NET
22
tristate "Microsoft Hyper-V virtual network driver"
33
depends on HYPERV
44
select UCS2_STRING
5-
select FAILOVER
65
help
76
Select this option to enable the Hyper-V virtual network driver.

drivers/net/hyperv/hyperv_net.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -931,8 +931,6 @@ struct net_device_context {
931931
u32 vf_alloc;
932932
/* Serial number of the VF to team with */
933933
u32 vf_serial;
934-
935-
struct failover *failover;
936934
};
937935

938936
/* Per channel data */

drivers/net/hyperv/netvsc_drv.c

Lines changed: 165 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
#include <net/pkt_sched.h>
4343
#include <net/checksum.h>
4444
#include <net/ip6_checksum.h>
45-
#include <net/failover.h>
4645

4746
#include "hyperv_net.h"
4847

@@ -1780,6 +1779,46 @@ static void netvsc_link_change(struct work_struct *w)
17801779
rtnl_unlock();
17811780
}
17821781

1782+
static struct net_device *get_netvsc_bymac(const u8 *mac)
1783+
{
1784+
struct net_device *dev;
1785+
1786+
ASSERT_RTNL();
1787+
1788+
for_each_netdev(&init_net, dev) {
1789+
if (dev->netdev_ops != &device_ops)
1790+
continue; /* not a netvsc device */
1791+
1792+
if (ether_addr_equal(mac, dev->perm_addr))
1793+
return dev;
1794+
}
1795+
1796+
return NULL;
1797+
}
1798+
1799+
static struct net_device *get_netvsc_byref(struct net_device *vf_netdev)
1800+
{
1801+
struct net_device *dev;
1802+
1803+
ASSERT_RTNL();
1804+
1805+
for_each_netdev(&init_net, dev) {
1806+
struct net_device_context *net_device_ctx;
1807+
1808+
if (dev->netdev_ops != &device_ops)
1809+
continue; /* not a netvsc device */
1810+
1811+
net_device_ctx = netdev_priv(dev);
1812+
if (!rtnl_dereference(net_device_ctx->nvdev))
1813+
continue; /* device is removed */
1814+
1815+
if (rtnl_dereference(net_device_ctx->vf_netdev) == vf_netdev)
1816+
return dev; /* a match */
1817+
}
1818+
1819+
return NULL;
1820+
}
1821+
17831822
/* Called when VF is injecting data into network stack.
17841823
* Change the associated network device from VF to netvsc.
17851824
* note: already called with rcu_read_lock
@@ -1802,6 +1841,46 @@ static rx_handler_result_t netvsc_vf_handle_frame(struct sk_buff **pskb)
18021841
return RX_HANDLER_ANOTHER;
18031842
}
18041843

1844+
static int netvsc_vf_join(struct net_device *vf_netdev,
1845+
struct net_device *ndev)
1846+
{
1847+
struct net_device_context *ndev_ctx = netdev_priv(ndev);
1848+
int ret;
1849+
1850+
ret = netdev_rx_handler_register(vf_netdev,
1851+
netvsc_vf_handle_frame, ndev);
1852+
if (ret != 0) {
1853+
netdev_err(vf_netdev,
1854+
"can not register netvsc VF receive handler (err = %d)\n",
1855+
ret);
1856+
goto rx_handler_failed;
1857+
}
1858+
1859+
ret = netdev_master_upper_dev_link(vf_netdev, ndev,
1860+
NULL, NULL, NULL);
1861+
if (ret != 0) {
1862+
netdev_err(vf_netdev,
1863+
"can not set master device %s (err = %d)\n",
1864+
ndev->name, ret);
1865+
goto upper_link_failed;
1866+
}
1867+
1868+
/* set slave flag before open to prevent IPv6 addrconf */
1869+
vf_netdev->flags |= IFF_SLAVE;
1870+
1871+
schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
1872+
1873+
call_netdevice_notifiers(NETDEV_JOIN, vf_netdev);
1874+
1875+
netdev_info(vf_netdev, "joined to %s\n", ndev->name);
1876+
return 0;
1877+
1878+
upper_link_failed:
1879+
netdev_rx_handler_unregister(vf_netdev);
1880+
rx_handler_failed:
1881+
return ret;
1882+
}
1883+
18051884
static void __netvsc_vf_setup(struct net_device *ndev,
18061885
struct net_device *vf_netdev)
18071886
{
@@ -1852,95 +1931,85 @@ static void netvsc_vf_setup(struct work_struct *w)
18521931
rtnl_unlock();
18531932
}
18541933

1855-
static int netvsc_pre_register_vf(struct net_device *vf_netdev,
1856-
struct net_device *ndev)
1934+
static int netvsc_register_vf(struct net_device *vf_netdev)
18571935
{
1936+
struct net_device *ndev;
18581937
struct net_device_context *net_device_ctx;
18591938
struct netvsc_device *netvsc_dev;
18601939

1940+
if (vf_netdev->addr_len != ETH_ALEN)
1941+
return NOTIFY_DONE;
1942+
1943+
/*
1944+
* We will use the MAC address to locate the synthetic interface to
1945+
* associate with the VF interface. If we don't find a matching
1946+
* synthetic interface, move on.
1947+
*/
1948+
ndev = get_netvsc_bymac(vf_netdev->perm_addr);
1949+
if (!ndev)
1950+
return NOTIFY_DONE;
1951+
18611952
net_device_ctx = netdev_priv(ndev);
18621953
netvsc_dev = rtnl_dereference(net_device_ctx->nvdev);
18631954
if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev))
1864-
return -ENODEV;
1865-
1866-
return 0;
1867-
}
1868-
1869-
static int netvsc_register_vf(struct net_device *vf_netdev,
1870-
struct net_device *ndev)
1871-
{
1872-
struct net_device_context *ndev_ctx = netdev_priv(ndev);
1873-
1874-
/* set slave flag before open to prevent IPv6 addrconf */
1875-
vf_netdev->flags |= IFF_SLAVE;
1955+
return NOTIFY_DONE;
18761956

1877-
schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
1957+
if (netvsc_vf_join(vf_netdev, ndev) != 0)
1958+
return NOTIFY_DONE;
18781959

1879-
call_netdevice_notifiers(NETDEV_JOIN, vf_netdev);
1880-
1881-
netdev_info(vf_netdev, "joined to %s\n", ndev->name);
1960+
netdev_info(ndev, "VF registering: %s\n", vf_netdev->name);
18821961

18831962
dev_hold(vf_netdev);
1884-
rcu_assign_pointer(ndev_ctx->vf_netdev, vf_netdev);
1885-
1886-
return 0;
1963+
rcu_assign_pointer(net_device_ctx->vf_netdev, vf_netdev);
1964+
return NOTIFY_OK;
18871965
}
18881966

18891967
/* VF up/down change detected, schedule to change data path */
1890-
static int netvsc_vf_changed(struct net_device *vf_netdev,
1891-
struct net_device *ndev)
1968+
static int netvsc_vf_changed(struct net_device *vf_netdev)
18921969
{
18931970
struct net_device_context *net_device_ctx;
18941971
struct netvsc_device *netvsc_dev;
1972+
struct net_device *ndev;
18951973
bool vf_is_up = netif_running(vf_netdev);
18961974

1975+
ndev = get_netvsc_byref(vf_netdev);
1976+
if (!ndev)
1977+
return NOTIFY_DONE;
1978+
18971979
net_device_ctx = netdev_priv(ndev);
18981980
netvsc_dev = rtnl_dereference(net_device_ctx->nvdev);
18991981
if (!netvsc_dev)
1900-
return -ENODEV;
1982+
return NOTIFY_DONE;
19011983

19021984
netvsc_switch_datapath(ndev, vf_is_up);
19031985
netdev_info(ndev, "Data path switched %s VF: %s\n",
19041986
vf_is_up ? "to" : "from", vf_netdev->name);
19051987

1906-
return 0;
1988+
return NOTIFY_OK;
19071989
}
19081990

1909-
static int netvsc_pre_unregister_vf(struct net_device *vf_netdev,
1910-
struct net_device *ndev)
1991+
static int netvsc_unregister_vf(struct net_device *vf_netdev)
19111992
{
1993+
struct net_device *ndev;
19121994
struct net_device_context *net_device_ctx;
19131995

1914-
net_device_ctx = netdev_priv(ndev);
1915-
cancel_delayed_work_sync(&net_device_ctx->vf_takeover);
1916-
1917-
return 0;
1918-
}
1919-
1920-
static int netvsc_unregister_vf(struct net_device *vf_netdev,
1921-
struct net_device *ndev)
1922-
{
1923-
struct net_device_context *net_device_ctx;
1996+
ndev = get_netvsc_byref(vf_netdev);
1997+
if (!ndev)
1998+
return NOTIFY_DONE;
19241999

19252000
net_device_ctx = netdev_priv(ndev);
2001+
cancel_delayed_work_sync(&net_device_ctx->vf_takeover);
19262002

19272003
netdev_info(ndev, "VF unregistering: %s\n", vf_netdev->name);
19282004

2005+
netdev_rx_handler_unregister(vf_netdev);
2006+
netdev_upper_dev_unlink(vf_netdev, ndev);
19292007
RCU_INIT_POINTER(net_device_ctx->vf_netdev, NULL);
19302008
dev_put(vf_netdev);
19312009

1932-
return 0;
2010+
return NOTIFY_OK;
19332011
}
19342012

1935-
static struct failover_ops netvsc_failover_ops = {
1936-
.slave_pre_register = netvsc_pre_register_vf,
1937-
.slave_register = netvsc_register_vf,
1938-
.slave_pre_unregister = netvsc_pre_unregister_vf,
1939-
.slave_unregister = netvsc_unregister_vf,
1940-
.slave_link_change = netvsc_vf_changed,
1941-
.slave_handle_frame = netvsc_vf_handle_frame,
1942-
};
1943-
19442013
static int netvsc_probe(struct hv_device *dev,
19452014
const struct hv_vmbus_device_id *dev_id)
19462015
{
@@ -2030,16 +2099,8 @@ static int netvsc_probe(struct hv_device *dev,
20302099
goto register_failed;
20312100
}
20322101

2033-
net_device_ctx->failover = failover_register(net, &netvsc_failover_ops);
2034-
if (IS_ERR(net_device_ctx->failover)) {
2035-
ret = PTR_ERR(net_device_ctx->failover);
2036-
goto err_failover;
2037-
}
2038-
20392102
return ret;
20402103

2041-
err_failover:
2042-
unregister_netdev(net);
20432104
register_failed:
20442105
rndis_filter_device_remove(dev, nvdev);
20452106
rndis_failed:
@@ -2080,15 +2141,13 @@ static int netvsc_remove(struct hv_device *dev)
20802141
rtnl_lock();
20812142
vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev);
20822143
if (vf_netdev)
2083-
failover_slave_unregister(vf_netdev);
2144+
netvsc_unregister_vf(vf_netdev);
20842145

20852146
if (nvdev)
20862147
rndis_filter_device_remove(dev, nvdev);
20872148

20882149
unregister_netdevice(net);
20892150

2090-
failover_unregister(ndev_ctx->failover);
2091-
20922151
rtnl_unlock();
20932152
rcu_read_unlock();
20942153

@@ -2115,8 +2174,54 @@ static struct hv_driver netvsc_drv = {
21152174
.remove = netvsc_remove,
21162175
};
21172176

2177+
/*
2178+
* On Hyper-V, every VF interface is matched with a corresponding
2179+
* synthetic interface. The synthetic interface is presented first
2180+
* to the guest. When the corresponding VF instance is registered,
2181+
* we will take care of switching the data path.
2182+
*/
2183+
static int netvsc_netdev_event(struct notifier_block *this,
2184+
unsigned long event, void *ptr)
2185+
{
2186+
struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
2187+
2188+
/* Skip our own events */
2189+
if (event_dev->netdev_ops == &device_ops)
2190+
return NOTIFY_DONE;
2191+
2192+
/* Avoid non-Ethernet type devices */
2193+
if (event_dev->type != ARPHRD_ETHER)
2194+
return NOTIFY_DONE;
2195+
2196+
/* Avoid Vlan dev with same MAC registering as VF */
2197+
if (is_vlan_dev(event_dev))
2198+
return NOTIFY_DONE;
2199+
2200+
/* Avoid Bonding master dev with same MAC registering as VF */
2201+
if ((event_dev->priv_flags & IFF_BONDING) &&
2202+
(event_dev->flags & IFF_MASTER))
2203+
return NOTIFY_DONE;
2204+
2205+
switch (event) {
2206+
case NETDEV_REGISTER:
2207+
return netvsc_register_vf(event_dev);
2208+
case NETDEV_UNREGISTER:
2209+
return netvsc_unregister_vf(event_dev);
2210+
case NETDEV_UP:
2211+
case NETDEV_DOWN:
2212+
return netvsc_vf_changed(event_dev);
2213+
default:
2214+
return NOTIFY_DONE;
2215+
}
2216+
}
2217+
2218+
static struct notifier_block netvsc_netdev_notifier = {
2219+
.notifier_call = netvsc_netdev_event,
2220+
};
2221+
21182222
static void __exit netvsc_drv_exit(void)
21192223
{
2224+
unregister_netdevice_notifier(&netvsc_netdev_notifier);
21202225
vmbus_driver_unregister(&netvsc_drv);
21212226
}
21222227

@@ -2135,6 +2240,7 @@ static int __init netvsc_drv_init(void)
21352240
if (ret)
21362241
return ret;
21372242

2243+
register_netdevice_notifier(&netvsc_netdev_notifier);
21382244
return 0;
21392245
}
21402246

0 commit comments

Comments
 (0)