Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /* Copyright (c) 2018, Intel Corporation. */
3 :
4 : /* A common module to handle registrations and notifications for paravirtual
5 : * drivers to enable accelerated datapath and support VF live migration.
6 : *
7 : * The notifier and event handling code is based on netvsc driver.
8 : */
9 :
10 : #include <linux/module.h>
11 : #include <linux/etherdevice.h>
12 : #include <uapi/linux/if_arp.h>
13 : #include <linux/rtnetlink.h>
14 : #include <linux/if_vlan.h>
15 : #include <net/failover.h>
16 :
17 : static LIST_HEAD(failover_list);
18 : static DEFINE_SPINLOCK(failover_lock);
19 :
20 1 : static struct net_device *failover_get_bymac(u8 *mac, struct failover_ops **ops)
21 : {
22 1 : struct net_device *failover_dev;
23 1 : struct failover *failover;
24 :
25 1 : spin_lock(&failover_lock);
26 1 : list_for_each_entry(failover, &failover_list, list) {
27 0 : failover_dev = rtnl_dereference(failover->failover_dev);
28 0 : if (ether_addr_equal(failover_dev->perm_addr, mac)) {
29 0 : *ops = rtnl_dereference(failover->ops);
30 0 : spin_unlock(&failover_lock);
31 0 : return failover_dev;
32 : }
33 : }
34 1 : spin_unlock(&failover_lock);
35 1 : return NULL;
36 : }
37 :
38 : /**
39 : * failover_slave_register - Register a slave netdev
40 : *
41 : * @slave_dev: slave netdev that is being registered
42 : *
43 : * Registers a slave device to a failover instance. Only ethernet devices
44 : * are supported.
45 : */
46 2 : static int failover_slave_register(struct net_device *slave_dev)
47 : {
48 2 : struct netdev_lag_upper_info lag_upper_info;
49 2 : struct net_device *failover_dev;
50 2 : struct failover_ops *fops;
51 2 : int err;
52 :
53 2 : if (slave_dev->type != ARPHRD_ETHER)
54 1 : goto done;
55 :
56 1 : ASSERT_RTNL();
57 :
58 1 : failover_dev = failover_get_bymac(slave_dev->perm_addr, &fops);
59 1 : if (!failover_dev)
60 1 : goto done;
61 :
62 0 : if (fops && fops->slave_pre_register &&
63 0 : fops->slave_pre_register(slave_dev, failover_dev))
64 0 : goto done;
65 :
66 0 : err = netdev_rx_handler_register(slave_dev, fops->slave_handle_frame,
67 : failover_dev);
68 0 : if (err) {
69 0 : netdev_err(slave_dev, "can not register failover rx handler (err = %d)\n",
70 : err);
71 0 : goto done;
72 : }
73 :
74 0 : lag_upper_info.tx_type = NETDEV_LAG_TX_TYPE_ACTIVEBACKUP;
75 0 : err = netdev_master_upper_dev_link(slave_dev, failover_dev, NULL,
76 : &lag_upper_info, NULL);
77 0 : if (err) {
78 0 : netdev_err(slave_dev, "can not set failover device %s (err = %d)\n",
79 0 : failover_dev->name, err);
80 0 : goto err_upper_link;
81 : }
82 :
83 0 : slave_dev->priv_flags |= (IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK);
84 :
85 0 : if (fops && fops->slave_register &&
86 0 : !fops->slave_register(slave_dev, failover_dev))
87 : return NOTIFY_OK;
88 :
89 0 : netdev_upper_dev_unlink(slave_dev, failover_dev);
90 0 : slave_dev->priv_flags &= ~(IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK);
91 0 : err_upper_link:
92 0 : netdev_rx_handler_unregister(slave_dev);
93 : done:
94 : return NOTIFY_DONE;
95 : }
96 :
97 : /**
98 : * failover_slave_unregister - Unregister a slave netdev
99 : *
100 : * @slave_dev: slave netdev that is being unregistered
101 : *
102 : * Unregisters a slave device from a failover instance.
103 : */
104 0 : int failover_slave_unregister(struct net_device *slave_dev)
105 : {
106 0 : struct net_device *failover_dev;
107 0 : struct failover_ops *fops;
108 :
109 0 : if (!netif_is_failover_slave(slave_dev))
110 0 : goto done;
111 :
112 0 : ASSERT_RTNL();
113 :
114 0 : failover_dev = failover_get_bymac(slave_dev->perm_addr, &fops);
115 0 : if (!failover_dev)
116 0 : goto done;
117 :
118 0 : if (fops && fops->slave_pre_unregister &&
119 0 : fops->slave_pre_unregister(slave_dev, failover_dev))
120 0 : goto done;
121 :
122 0 : netdev_rx_handler_unregister(slave_dev);
123 0 : netdev_upper_dev_unlink(slave_dev, failover_dev);
124 0 : slave_dev->priv_flags &= ~(IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK);
125 :
126 0 : if (fops && fops->slave_unregister &&
127 0 : !fops->slave_unregister(slave_dev, failover_dev))
128 0 : return NOTIFY_OK;
129 :
130 0 : done:
131 : return NOTIFY_DONE;
132 : }
133 : EXPORT_SYMBOL_GPL(failover_slave_unregister);
134 :
135 2 : static int failover_slave_link_change(struct net_device *slave_dev)
136 : {
137 2 : struct net_device *failover_dev;
138 2 : struct failover_ops *fops;
139 :
140 2 : if (!netif_is_failover_slave(slave_dev))
141 2 : goto done;
142 :
143 0 : ASSERT_RTNL();
144 :
145 0 : failover_dev = failover_get_bymac(slave_dev->perm_addr, &fops);
146 0 : if (!failover_dev)
147 0 : goto done;
148 :
149 0 : if (!netif_running(failover_dev))
150 0 : goto done;
151 :
152 0 : if (fops && fops->slave_link_change &&
153 0 : !fops->slave_link_change(slave_dev, failover_dev))
154 0 : return NOTIFY_OK;
155 :
156 0 : done:
157 : return NOTIFY_DONE;
158 : }
159 :
160 0 : static int failover_slave_name_change(struct net_device *slave_dev)
161 : {
162 0 : struct net_device *failover_dev;
163 0 : struct failover_ops *fops;
164 :
165 0 : if (!netif_is_failover_slave(slave_dev))
166 0 : goto done;
167 :
168 0 : ASSERT_RTNL();
169 :
170 0 : failover_dev = failover_get_bymac(slave_dev->perm_addr, &fops);
171 0 : if (!failover_dev)
172 0 : goto done;
173 :
174 0 : if (!netif_running(failover_dev))
175 0 : goto done;
176 :
177 0 : if (fops && fops->slave_name_change &&
178 0 : !fops->slave_name_change(slave_dev, failover_dev))
179 0 : return NOTIFY_OK;
180 :
181 0 : done:
182 : return NOTIFY_DONE;
183 : }
184 :
185 : static int
186 6 : failover_event(struct notifier_block *this, unsigned long event, void *ptr)
187 : {
188 6 : struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
189 :
190 : /* Skip parent events */
191 6 : if (netif_is_failover(event_dev))
192 : return NOTIFY_DONE;
193 :
194 6 : switch (event) {
195 2 : case NETDEV_REGISTER:
196 2 : return failover_slave_register(event_dev);
197 0 : case NETDEV_UNREGISTER:
198 0 : return failover_slave_unregister(event_dev);
199 2 : case NETDEV_UP:
200 : case NETDEV_DOWN:
201 : case NETDEV_CHANGE:
202 2 : return failover_slave_link_change(event_dev);
203 0 : case NETDEV_CHANGENAME:
204 0 : return failover_slave_name_change(event_dev);
205 : default:
206 : return NOTIFY_DONE;
207 : }
208 : }
209 :
210 : static struct notifier_block failover_notifier = {
211 : .notifier_call = failover_event,
212 : };
213 :
214 : static void
215 0 : failover_existing_slave_register(struct net_device *failover_dev)
216 : {
217 0 : struct net *net = dev_net(failover_dev);
218 0 : struct net_device *dev;
219 :
220 0 : rtnl_lock();
221 0 : for_each_netdev(net, dev) {
222 0 : if (netif_is_failover(dev))
223 0 : continue;
224 0 : if (ether_addr_equal(failover_dev->perm_addr, dev->perm_addr))
225 0 : failover_slave_register(dev);
226 : }
227 0 : rtnl_unlock();
228 0 : }
229 :
230 : /**
231 : * failover_register - Register a failover instance
232 : *
233 : * @dev: failover netdev
234 : * @ops: failover ops
235 : *
236 : * Allocate and register a failover instance for a failover netdev. ops
237 : * provides handlers for slave device register/unregister/link change/
238 : * name change events.
239 : *
240 : * Return: pointer to failover instance
241 : */
242 0 : struct failover *failover_register(struct net_device *dev,
243 : struct failover_ops *ops)
244 : {
245 0 : struct failover *failover;
246 :
247 0 : if (dev->type != ARPHRD_ETHER)
248 0 : return ERR_PTR(-EINVAL);
249 :
250 0 : failover = kzalloc(sizeof(*failover), GFP_KERNEL);
251 0 : if (!failover)
252 0 : return ERR_PTR(-ENOMEM);
253 :
254 0 : rcu_assign_pointer(failover->ops, ops);
255 0 : dev_hold(dev);
256 0 : dev->priv_flags |= IFF_FAILOVER;
257 0 : rcu_assign_pointer(failover->failover_dev, dev);
258 :
259 0 : spin_lock(&failover_lock);
260 0 : list_add_tail(&failover->list, &failover_list);
261 0 : spin_unlock(&failover_lock);
262 :
263 0 : netdev_info(dev, "failover master:%s registered\n", dev->name);
264 :
265 0 : failover_existing_slave_register(dev);
266 :
267 0 : return failover;
268 : }
269 : EXPORT_SYMBOL_GPL(failover_register);
270 :
271 : /**
272 : * failover_unregister - Unregister a failover instance
273 : *
274 : * @failover: pointer to failover instance
275 : *
276 : * Unregisters and frees a failover instance.
277 : */
278 0 : void failover_unregister(struct failover *failover)
279 : {
280 0 : struct net_device *failover_dev;
281 :
282 0 : failover_dev = rcu_dereference(failover->failover_dev);
283 :
284 0 : netdev_info(failover_dev, "failover master:%s unregistered\n",
285 0 : failover_dev->name);
286 :
287 0 : failover_dev->priv_flags &= ~IFF_FAILOVER;
288 0 : dev_put(failover_dev);
289 :
290 0 : spin_lock(&failover_lock);
291 0 : list_del(&failover->list);
292 0 : spin_unlock(&failover_lock);
293 :
294 0 : kfree(failover);
295 0 : }
296 : EXPORT_SYMBOL_GPL(failover_unregister);
297 :
298 : static __init int
299 1 : failover_init(void)
300 : {
301 1 : register_netdevice_notifier(&failover_notifier);
302 :
303 1 : return 0;
304 : }
305 : module_init(failover_init);
306 :
307 : static __exit
308 0 : void failover_exit(void)
309 : {
310 0 : unregister_netdevice_notifier(&failover_notifier);
311 0 : }
312 : module_exit(failover_exit);
313 :
314 : MODULE_DESCRIPTION("Generic failover infrastructure/interface");
315 : MODULE_LICENSE("GPL v2");
|