Skip to content

Commit 1ff7807

Browse files
ssamudraladavem330
authored andcommitted
netvsc: refactor notifier/event handling code to use the failover framework
Use the registration/notification framework supported by the generic failover infrastructure. Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 30c8bd5 commit 1ff7807

File tree

3 files changed

+60
-165
lines changed

3 files changed

+60
-165
lines changed

drivers/net/hyperv/Kconfig

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

drivers/net/hyperv/hyperv_net.h

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

937939
/* Per channel data */

drivers/net/hyperv/netvsc_drv.c

Lines changed: 57 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <net/pkt_sched.h>
4444
#include <net/checksum.h>
4545
#include <net/ip6_checksum.h>
46+
#include <net/failover.h>
4647

4748
#include "hyperv_net.h"
4849

@@ -1779,46 +1780,6 @@ static void netvsc_link_change(struct work_struct *w)
17791780
rtnl_unlock();
17801781
}
17811782

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-
18221783
/* Called when VF is injecting data into network stack.
18231784
* Change the associated network device from VF to netvsc.
18241785
* note: already called with rcu_read_lock
@@ -1841,46 +1802,6 @@ static rx_handler_result_t netvsc_vf_handle_frame(struct sk_buff **pskb)
18411802
return RX_HANDLER_ANOTHER;
18421803
}
18431804

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-
18841805
static void __netvsc_vf_setup(struct net_device *ndev,
18851806
struct net_device *vf_netdev)
18861807
{
@@ -1931,85 +1852,95 @@ static void netvsc_vf_setup(struct work_struct *w)
19311852
rtnl_unlock();
19321853
}
19331854

1934-
static int netvsc_register_vf(struct net_device *vf_netdev)
1855+
static int netvsc_pre_register_vf(struct net_device *vf_netdev,
1856+
struct net_device *ndev)
19351857
{
1936-
struct net_device *ndev;
19371858
struct net_device_context *net_device_ctx;
19381859
struct netvsc_device *netvsc_dev;
19391860

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-
19521861
net_device_ctx = netdev_priv(ndev);
19531862
netvsc_dev = rtnl_dereference(net_device_ctx->nvdev);
19541863
if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev))
1955-
return NOTIFY_DONE;
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);
19561873

1957-
if (netvsc_vf_join(vf_netdev, ndev) != 0)
1958-
return NOTIFY_DONE;
1874+
/* set slave flag before open to prevent IPv6 addrconf */
1875+
vf_netdev->flags |= IFF_SLAVE;
19591876

1960-
netdev_info(ndev, "VF registering: %s\n", vf_netdev->name);
1877+
schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
1878+
1879+
call_netdevice_notifiers(NETDEV_JOIN, vf_netdev);
1880+
1881+
netdev_info(vf_netdev, "joined to %s\n", ndev->name);
19611882

19621883
dev_hold(vf_netdev);
1963-
rcu_assign_pointer(net_device_ctx->vf_netdev, vf_netdev);
1964-
return NOTIFY_OK;
1884+
rcu_assign_pointer(ndev_ctx->vf_netdev, vf_netdev);
1885+
1886+
return 0;
19651887
}
19661888

19671889
/* VF up/down change detected, schedule to change data path */
1968-
static int netvsc_vf_changed(struct net_device *vf_netdev)
1890+
static int netvsc_vf_changed(struct net_device *vf_netdev,
1891+
struct net_device *ndev)
19691892
{
19701893
struct net_device_context *net_device_ctx;
19711894
struct netvsc_device *netvsc_dev;
1972-
struct net_device *ndev;
19731895
bool vf_is_up = netif_running(vf_netdev);
19741896

1975-
ndev = get_netvsc_byref(vf_netdev);
1976-
if (!ndev)
1977-
return NOTIFY_DONE;
1978-
19791897
net_device_ctx = netdev_priv(ndev);
19801898
netvsc_dev = rtnl_dereference(net_device_ctx->nvdev);
19811899
if (!netvsc_dev)
1982-
return NOTIFY_DONE;
1900+
return -ENODEV;
19831901

19841902
netvsc_switch_datapath(ndev, vf_is_up);
19851903
netdev_info(ndev, "Data path switched %s VF: %s\n",
19861904
vf_is_up ? "to" : "from", vf_netdev->name);
19871905

1988-
return NOTIFY_OK;
1906+
return 0;
19891907
}
19901908

1991-
static int netvsc_unregister_vf(struct net_device *vf_netdev)
1909+
static int netvsc_pre_unregister_vf(struct net_device *vf_netdev,
1910+
struct net_device *ndev)
19921911
{
1993-
struct net_device *ndev;
19941912
struct net_device_context *net_device_ctx;
19951913

1996-
ndev = get_netvsc_byref(vf_netdev);
1997-
if (!ndev)
1998-
return NOTIFY_DONE;
1999-
20001914
net_device_ctx = netdev_priv(ndev);
20011915
cancel_delayed_work_sync(&net_device_ctx->vf_takeover);
20021916

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;
1924+
1925+
net_device_ctx = netdev_priv(ndev);
1926+
20031927
netdev_info(ndev, "VF unregistering: %s\n", vf_netdev->name);
20041928

2005-
netdev_rx_handler_unregister(vf_netdev);
2006-
netdev_upper_dev_unlink(vf_netdev, ndev);
20071929
RCU_INIT_POINTER(net_device_ctx->vf_netdev, NULL);
20081930
dev_put(vf_netdev);
20091931

2010-
return NOTIFY_OK;
1932+
return 0;
20111933
}
20121934

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+
20131944
static int netvsc_probe(struct hv_device *dev,
20141945
const struct hv_vmbus_device_id *dev_id)
20151946
{
@@ -2099,8 +2030,14 @@ static int netvsc_probe(struct hv_device *dev,
20992030
goto register_failed;
21002031
}
21012032

2033+
net_device_ctx->failover = failover_register(net, &netvsc_failover_ops);
2034+
if (IS_ERR(net_device_ctx->failover))
2035+
goto err_failover;
2036+
21022037
return ret;
21032038

2039+
err_failover:
2040+
unregister_netdev(net);
21042041
register_failed:
21052042
rndis_filter_device_remove(dev, nvdev);
21062043
rndis_failed:
@@ -2141,13 +2078,15 @@ static int netvsc_remove(struct hv_device *dev)
21412078
rtnl_lock();
21422079
vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev);
21432080
if (vf_netdev)
2144-
netvsc_unregister_vf(vf_netdev);
2081+
failover_slave_unregister(vf_netdev);
21452082

21462083
if (nvdev)
21472084
rndis_filter_device_remove(dev, nvdev);
21482085

21492086
unregister_netdevice(net);
21502087

2088+
failover_unregister(ndev_ctx->failover);
2089+
21512090
rtnl_unlock();
21522091
rcu_read_unlock();
21532092

@@ -2174,54 +2113,8 @@ static struct hv_driver netvsc_drv = {
21742113
.remove = netvsc_remove,
21752114
};
21762115

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-
22222116
static void __exit netvsc_drv_exit(void)
22232117
{
2224-
unregister_netdevice_notifier(&netvsc_netdev_notifier);
22252118
vmbus_driver_unregister(&netvsc_drv);
22262119
}
22272120

@@ -2241,7 +2134,6 @@ static int __init netvsc_drv_init(void)
22412134
if (ret)
22422135
return ret;
22432136

2244-
register_netdevice_notifier(&netvsc_netdev_notifier);
22452137
return 0;
22462138
}
22472139

0 commit comments

Comments
 (0)