|
@@ -30,8 +30,11 @@
|
|
#include <linux/cpu.h>
|
|
#include <linux/cpu.h>
|
|
#include <linux/average.h>
|
|
#include <linux/average.h>
|
|
#include <linux/filter.h>
|
|
#include <linux/filter.h>
|
|
|
|
+#include <linux/netdevice.h>
|
|
|
|
+#include <linux/pci.h>
|
|
#include <net/route.h>
|
|
#include <net/route.h>
|
|
#include <net/xdp.h>
|
|
#include <net/xdp.h>
|
|
|
|
+#include <net/net_failover.h>
|
|
|
|
|
|
static int napi_weight = NAPI_POLL_WEIGHT;
|
|
static int napi_weight = NAPI_POLL_WEIGHT;
|
|
module_param(napi_weight, int, 0444);
|
|
module_param(napi_weight, int, 0444);
|
|
@@ -210,6 +213,9 @@ struct virtnet_info {
|
|
u32 speed;
|
|
u32 speed;
|
|
|
|
|
|
unsigned long guest_offloads;
|
|
unsigned long guest_offloads;
|
|
|
|
+
|
|
|
|
+ /* failover when STANDBY feature enabled */
|
|
|
|
+ struct failover *failover;
|
|
};
|
|
};
|
|
|
|
|
|
struct padded_vnet_hdr {
|
|
struct padded_vnet_hdr {
|
|
@@ -1554,6 +1560,9 @@ static int virtnet_set_mac_address(struct net_device *dev, void *p)
|
|
struct sockaddr *addr;
|
|
struct sockaddr *addr;
|
|
struct scatterlist sg;
|
|
struct scatterlist sg;
|
|
|
|
|
|
|
|
+ if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STANDBY))
|
|
|
|
+ return -EOPNOTSUPP;
|
|
|
|
+
|
|
addr = kmemdup(p, sizeof(*addr), GFP_KERNEL);
|
|
addr = kmemdup(p, sizeof(*addr), GFP_KERNEL);
|
|
if (!addr)
|
|
if (!addr)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
@@ -2337,6 +2346,22 @@ static int virtnet_xdp(struct net_device *dev, struct netdev_bpf *xdp)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int virtnet_get_phys_port_name(struct net_device *dev, char *buf,
|
|
|
|
+ size_t len)
|
|
|
|
+{
|
|
|
|
+ struct virtnet_info *vi = netdev_priv(dev);
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_STANDBY))
|
|
|
|
+ return -EOPNOTSUPP;
|
|
|
|
+
|
|
|
|
+ ret = snprintf(buf, len, "sby");
|
|
|
|
+ if (ret >= len)
|
|
|
|
+ return -EOPNOTSUPP;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static const struct net_device_ops virtnet_netdev = {
|
|
static const struct net_device_ops virtnet_netdev = {
|
|
.ndo_open = virtnet_open,
|
|
.ndo_open = virtnet_open,
|
|
.ndo_stop = virtnet_close,
|
|
.ndo_stop = virtnet_close,
|
|
@@ -2354,6 +2379,7 @@ static const struct net_device_ops virtnet_netdev = {
|
|
.ndo_xdp_xmit = virtnet_xdp_xmit,
|
|
.ndo_xdp_xmit = virtnet_xdp_xmit,
|
|
.ndo_xdp_flush = virtnet_xdp_flush,
|
|
.ndo_xdp_flush = virtnet_xdp_flush,
|
|
.ndo_features_check = passthru_features_check,
|
|
.ndo_features_check = passthru_features_check,
|
|
|
|
+ .ndo_get_phys_port_name = virtnet_get_phys_port_name,
|
|
};
|
|
};
|
|
|
|
|
|
static void virtnet_config_changed_work(struct work_struct *work)
|
|
static void virtnet_config_changed_work(struct work_struct *work)
|
|
@@ -2907,10 +2933,16 @@ static int virtnet_probe(struct virtio_device *vdev)
|
|
|
|
|
|
virtnet_init_settings(dev);
|
|
virtnet_init_settings(dev);
|
|
|
|
|
|
|
|
+ if (virtio_has_feature(vdev, VIRTIO_NET_F_STANDBY)) {
|
|
|
|
+ vi->failover = net_failover_create(vi->dev);
|
|
|
|
+ if (IS_ERR(vi->failover))
|
|
|
|
+ goto free_vqs;
|
|
|
|
+ }
|
|
|
|
+
|
|
err = register_netdev(dev);
|
|
err = register_netdev(dev);
|
|
if (err) {
|
|
if (err) {
|
|
pr_debug("virtio_net: registering device failed\n");
|
|
pr_debug("virtio_net: registering device failed\n");
|
|
- goto free_vqs;
|
|
|
|
|
|
+ goto free_failover;
|
|
}
|
|
}
|
|
|
|
|
|
virtio_device_ready(vdev);
|
|
virtio_device_ready(vdev);
|
|
@@ -2947,6 +2979,8 @@ free_unregister_netdev:
|
|
vi->vdev->config->reset(vdev);
|
|
vi->vdev->config->reset(vdev);
|
|
|
|
|
|
unregister_netdev(dev);
|
|
unregister_netdev(dev);
|
|
|
|
+free_failover:
|
|
|
|
+ net_failover_destroy(vi->failover);
|
|
free_vqs:
|
|
free_vqs:
|
|
cancel_delayed_work_sync(&vi->refill);
|
|
cancel_delayed_work_sync(&vi->refill);
|
|
free_receive_page_frags(vi);
|
|
free_receive_page_frags(vi);
|
|
@@ -2981,6 +3015,8 @@ static void virtnet_remove(struct virtio_device *vdev)
|
|
|
|
|
|
unregister_netdev(vi->dev);
|
|
unregister_netdev(vi->dev);
|
|
|
|
|
|
|
|
+ net_failover_destroy(vi->failover);
|
|
|
|
+
|
|
remove_vq_common(vi);
|
|
remove_vq_common(vi);
|
|
|
|
|
|
free_netdev(vi->dev);
|
|
free_netdev(vi->dev);
|