Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (c) 2018, Intel Corporation. */
0003 
0004 /* A common module to handle registrations and notifications for paravirtual
0005  * drivers to enable accelerated datapath and support VF live migration.
0006  *
0007  * The notifier and event handling code is based on netvsc driver.
0008  */
0009 
0010 #include <linux/module.h>
0011 #include <linux/etherdevice.h>
0012 #include <uapi/linux/if_arp.h>
0013 #include <linux/rtnetlink.h>
0014 #include <linux/if_vlan.h>
0015 #include <net/failover.h>
0016 
0017 static LIST_HEAD(failover_list);
0018 static DEFINE_SPINLOCK(failover_lock);
0019 
0020 static struct net_device *failover_get_bymac(u8 *mac, struct failover_ops **ops)
0021 {
0022     struct net_device *failover_dev;
0023     struct failover *failover;
0024 
0025     spin_lock(&failover_lock);
0026     list_for_each_entry(failover, &failover_list, list) {
0027         failover_dev = rtnl_dereference(failover->failover_dev);
0028         if (ether_addr_equal(failover_dev->perm_addr, mac)) {
0029             *ops = rtnl_dereference(failover->ops);
0030             spin_unlock(&failover_lock);
0031             return failover_dev;
0032         }
0033     }
0034     spin_unlock(&failover_lock);
0035     return NULL;
0036 }
0037 
0038 /**
0039  * failover_slave_register - Register a slave netdev
0040  *
0041  * @slave_dev: slave netdev that is being registered
0042  *
0043  * Registers a slave device to a failover instance. Only ethernet devices
0044  * are supported.
0045  */
0046 static int failover_slave_register(struct net_device *slave_dev)
0047 {
0048     struct netdev_lag_upper_info lag_upper_info;
0049     struct net_device *failover_dev;
0050     struct failover_ops *fops;
0051     int err;
0052 
0053     if (slave_dev->type != ARPHRD_ETHER)
0054         goto done;
0055 
0056     ASSERT_RTNL();
0057 
0058     failover_dev = failover_get_bymac(slave_dev->perm_addr, &fops);
0059     if (!failover_dev)
0060         goto done;
0061 
0062     if (fops && fops->slave_pre_register &&
0063         fops->slave_pre_register(slave_dev, failover_dev))
0064         goto done;
0065 
0066     err = netdev_rx_handler_register(slave_dev, fops->slave_handle_frame,
0067                      failover_dev);
0068     if (err) {
0069         netdev_err(slave_dev, "can not register failover rx handler (err = %d)\n",
0070                err);
0071         goto done;
0072     }
0073 
0074     lag_upper_info.tx_type = NETDEV_LAG_TX_TYPE_ACTIVEBACKUP;
0075     err = netdev_master_upper_dev_link(slave_dev, failover_dev, NULL,
0076                        &lag_upper_info, NULL);
0077     if (err) {
0078         netdev_err(slave_dev, "can not set failover device %s (err = %d)\n",
0079                failover_dev->name, err);
0080         goto err_upper_link;
0081     }
0082 
0083     slave_dev->priv_flags |= (IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK);
0084 
0085     if (fops && fops->slave_register &&
0086         !fops->slave_register(slave_dev, failover_dev))
0087         return NOTIFY_OK;
0088 
0089     netdev_upper_dev_unlink(slave_dev, failover_dev);
0090     slave_dev->priv_flags &= ~(IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK);
0091 err_upper_link:
0092     netdev_rx_handler_unregister(slave_dev);
0093 done:
0094     return NOTIFY_DONE;
0095 }
0096 
0097 /**
0098  * failover_slave_unregister - Unregister a slave netdev
0099  *
0100  * @slave_dev: slave netdev that is being unregistered
0101  *
0102  * Unregisters a slave device from a failover instance.
0103  */
0104 int failover_slave_unregister(struct net_device *slave_dev)
0105 {
0106     struct net_device *failover_dev;
0107     struct failover_ops *fops;
0108 
0109     if (!netif_is_failover_slave(slave_dev))
0110         goto done;
0111 
0112     ASSERT_RTNL();
0113 
0114     failover_dev = failover_get_bymac(slave_dev->perm_addr, &fops);
0115     if (!failover_dev)
0116         goto done;
0117 
0118     if (fops && fops->slave_pre_unregister &&
0119         fops->slave_pre_unregister(slave_dev, failover_dev))
0120         goto done;
0121 
0122     netdev_rx_handler_unregister(slave_dev);
0123     netdev_upper_dev_unlink(slave_dev, failover_dev);
0124     slave_dev->priv_flags &= ~(IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK);
0125 
0126     if (fops && fops->slave_unregister &&
0127         !fops->slave_unregister(slave_dev, failover_dev))
0128         return NOTIFY_OK;
0129 
0130 done:
0131     return NOTIFY_DONE;
0132 }
0133 EXPORT_SYMBOL_GPL(failover_slave_unregister);
0134 
0135 static int failover_slave_link_change(struct net_device *slave_dev)
0136 {
0137     struct net_device *failover_dev;
0138     struct failover_ops *fops;
0139 
0140     if (!netif_is_failover_slave(slave_dev))
0141         goto done;
0142 
0143     ASSERT_RTNL();
0144 
0145     failover_dev = failover_get_bymac(slave_dev->perm_addr, &fops);
0146     if (!failover_dev)
0147         goto done;
0148 
0149     if (!netif_running(failover_dev))
0150         goto done;
0151 
0152     if (fops && fops->slave_link_change &&
0153         !fops->slave_link_change(slave_dev, failover_dev))
0154         return NOTIFY_OK;
0155 
0156 done:
0157     return NOTIFY_DONE;
0158 }
0159 
0160 static int failover_slave_name_change(struct net_device *slave_dev)
0161 {
0162     struct net_device *failover_dev;
0163     struct failover_ops *fops;
0164 
0165     if (!netif_is_failover_slave(slave_dev))
0166         goto done;
0167 
0168     ASSERT_RTNL();
0169 
0170     failover_dev = failover_get_bymac(slave_dev->perm_addr, &fops);
0171     if (!failover_dev)
0172         goto done;
0173 
0174     if (!netif_running(failover_dev))
0175         goto done;
0176 
0177     if (fops && fops->slave_name_change &&
0178         !fops->slave_name_change(slave_dev, failover_dev))
0179         return NOTIFY_OK;
0180 
0181 done:
0182     return NOTIFY_DONE;
0183 }
0184 
0185 static int
0186 failover_event(struct notifier_block *this, unsigned long event, void *ptr)
0187 {
0188     struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
0189 
0190     /* Skip parent events */
0191     if (netif_is_failover(event_dev))
0192         return NOTIFY_DONE;
0193 
0194     switch (event) {
0195     case NETDEV_REGISTER:
0196         return failover_slave_register(event_dev);
0197     case NETDEV_UNREGISTER:
0198         return failover_slave_unregister(event_dev);
0199     case NETDEV_UP:
0200     case NETDEV_DOWN:
0201     case NETDEV_CHANGE:
0202         return failover_slave_link_change(event_dev);
0203     case NETDEV_CHANGENAME:
0204         return failover_slave_name_change(event_dev);
0205     default:
0206         return NOTIFY_DONE;
0207     }
0208 }
0209 
0210 static struct notifier_block failover_notifier = {
0211     .notifier_call = failover_event,
0212 };
0213 
0214 static void
0215 failover_existing_slave_register(struct net_device *failover_dev)
0216 {
0217     struct net *net = dev_net(failover_dev);
0218     struct net_device *dev;
0219 
0220     rtnl_lock();
0221     for_each_netdev(net, dev) {
0222         if (netif_is_failover(dev))
0223             continue;
0224         if (ether_addr_equal(failover_dev->perm_addr, dev->perm_addr))
0225             failover_slave_register(dev);
0226     }
0227     rtnl_unlock();
0228 }
0229 
0230 /**
0231  * failover_register - Register a failover instance
0232  *
0233  * @dev: failover netdev
0234  * @ops: failover ops
0235  *
0236  * Allocate and register a failover instance for a failover netdev. ops
0237  * provides handlers for slave device register/unregister/link change/
0238  * name change events.
0239  *
0240  * Return: pointer to failover instance
0241  */
0242 struct failover *failover_register(struct net_device *dev,
0243                    struct failover_ops *ops)
0244 {
0245     struct failover *failover;
0246 
0247     if (dev->type != ARPHRD_ETHER)
0248         return ERR_PTR(-EINVAL);
0249 
0250     failover = kzalloc(sizeof(*failover), GFP_KERNEL);
0251     if (!failover)
0252         return ERR_PTR(-ENOMEM);
0253 
0254     rcu_assign_pointer(failover->ops, ops);
0255     netdev_hold(dev, &failover->dev_tracker, GFP_KERNEL);
0256     dev->priv_flags |= IFF_FAILOVER;
0257     rcu_assign_pointer(failover->failover_dev, dev);
0258 
0259     spin_lock(&failover_lock);
0260     list_add_tail(&failover->list, &failover_list);
0261     spin_unlock(&failover_lock);
0262 
0263     netdev_info(dev, "failover master:%s registered\n", dev->name);
0264 
0265     failover_existing_slave_register(dev);
0266 
0267     return failover;
0268 }
0269 EXPORT_SYMBOL_GPL(failover_register);
0270 
0271 /**
0272  * failover_unregister - Unregister a failover instance
0273  *
0274  * @failover: pointer to failover instance
0275  *
0276  * Unregisters and frees a failover instance.
0277  */
0278 void failover_unregister(struct failover *failover)
0279 {
0280     struct net_device *failover_dev;
0281 
0282     failover_dev = rcu_dereference(failover->failover_dev);
0283 
0284     netdev_info(failover_dev, "failover master:%s unregistered\n",
0285             failover_dev->name);
0286 
0287     failover_dev->priv_flags &= ~IFF_FAILOVER;
0288     netdev_put(failover_dev, &failover->dev_tracker);
0289 
0290     spin_lock(&failover_lock);
0291     list_del(&failover->list);
0292     spin_unlock(&failover_lock);
0293 
0294     kfree(failover);
0295 }
0296 EXPORT_SYMBOL_GPL(failover_unregister);
0297 
0298 static __init int
0299 failover_init(void)
0300 {
0301     register_netdevice_notifier(&failover_notifier);
0302 
0303     return 0;
0304 }
0305 module_init(failover_init);
0306 
0307 static __exit
0308 void failover_exit(void)
0309 {
0310     unregister_netdevice_notifier(&failover_notifier);
0311 }
0312 module_exit(failover_exit);
0313 
0314 MODULE_DESCRIPTION("Generic failover infrastructure/interface");
0315 MODULE_LICENSE("GPL v2");