Skip to content

Commit 3f93522

Browse files
jasowangdavem330
authored andcommitted
virtio-net: switch off offloads on demand if possible on XDP set
Current XDP implementation wants guest offloads feature to be disabled on device. This is inconvenient and means guest can't benefit from offloads if XDP is not used. This patch tries to address this limitation by disabling the offloads on demand through control guest offloads. Guest offloads will be disabled and enabled on demand on XDP set. Signed-off-by: Jason Wang <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4941d47 commit 3f93522

File tree

1 file changed

+65
-5
lines changed

1 file changed

+65
-5
lines changed

drivers/net/virtio_net.c

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ DECLARE_EWMA(pkt_len, 0, 64)
5757

5858
#define VIRTNET_DRIVER_VERSION "1.0.0"
5959

60+
const unsigned long guest_offloads[] = { VIRTIO_NET_F_GUEST_TSO4,
61+
VIRTIO_NET_F_GUEST_TSO6,
62+
VIRTIO_NET_F_GUEST_ECN,
63+
VIRTIO_NET_F_GUEST_UFO };
64+
6065
struct virtnet_stats {
6166
struct u64_stats_sync tx_syncp;
6267
struct u64_stats_sync rx_syncp;
@@ -164,10 +169,13 @@ struct virtnet_info {
164169
u8 ctrl_promisc;
165170
u8 ctrl_allmulti;
166171
u16 ctrl_vid;
172+
u64 ctrl_offloads;
167173

168174
/* Ethtool settings */
169175
u8 duplex;
170176
u32 speed;
177+
178+
unsigned long guest_offloads;
171179
};
172180

173181
struct padded_vnet_hdr {
@@ -1897,6 +1905,47 @@ static int virtnet_restore_up(struct virtio_device *vdev)
18971905
return err;
18981906
}
18991907

1908+
static int virtnet_set_guest_offloads(struct virtnet_info *vi, u64 offloads)
1909+
{
1910+
struct scatterlist sg;
1911+
vi->ctrl_offloads = cpu_to_virtio64(vi->vdev, offloads);
1912+
1913+
sg_init_one(&sg, &vi->ctrl_offloads, sizeof(vi->ctrl_offloads));
1914+
1915+
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_GUEST_OFFLOADS,
1916+
VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET, &sg)) {
1917+
dev_warn(&vi->dev->dev, "Fail to set guest offload. \n");
1918+
return -EINVAL;
1919+
}
1920+
1921+
return 0;
1922+
}
1923+
1924+
static int virtnet_clear_guest_offloads(struct virtnet_info *vi)
1925+
{
1926+
u64 offloads = 0;
1927+
1928+
if (!vi->guest_offloads)
1929+
return 0;
1930+
1931+
if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_CSUM))
1932+
offloads = 1ULL << VIRTIO_NET_F_GUEST_CSUM;
1933+
1934+
return virtnet_set_guest_offloads(vi, offloads);
1935+
}
1936+
1937+
static int virtnet_restore_guest_offloads(struct virtnet_info *vi)
1938+
{
1939+
u64 offloads = vi->guest_offloads;
1940+
1941+
if (!vi->guest_offloads)
1942+
return 0;
1943+
if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_CSUM))
1944+
offloads |= 1ULL << VIRTIO_NET_F_GUEST_CSUM;
1945+
1946+
return virtnet_set_guest_offloads(vi, offloads);
1947+
}
1948+
19001949
static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
19011950
struct netlink_ext_ack *extack)
19021951
{
@@ -1906,10 +1955,11 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
19061955
u16 xdp_qp = 0, curr_qp;
19071956
int i, err;
19081957

1909-
if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO4) ||
1910-
virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO6) ||
1911-
virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_ECN) ||
1912-
virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_UFO)) {
1958+
if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)
1959+
&& (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO4) ||
1960+
virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO6) ||
1961+
virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_ECN) ||
1962+
virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_UFO))) {
19131963
NL_SET_ERR_MSG_MOD(extack, "Can't set XDP while host is implementing LRO, disable LRO first");
19141964
return -EOPNOTSUPP;
19151965
}
@@ -1956,6 +2006,12 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
19562006
for (i = 0; i < vi->max_queue_pairs; i++) {
19572007
old_prog = rtnl_dereference(vi->rq[i].xdp_prog);
19582008
rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
2009+
if (i == 0) {
2010+
if (!old_prog)
2011+
virtnet_clear_guest_offloads(vi);
2012+
if (!prog)
2013+
virtnet_restore_guest_offloads(vi);
2014+
}
19592015
if (old_prog)
19602016
bpf_prog_put(old_prog);
19612017
virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
@@ -2591,6 +2647,10 @@ static int virtnet_probe(struct virtio_device *vdev)
25912647
netif_carrier_on(dev);
25922648
}
25932649

2650+
for (i = 0; i < ARRAY_SIZE(guest_offloads); i++)
2651+
if (virtio_has_feature(vi->vdev, guest_offloads[i]))
2652+
set_bit(guest_offloads[i], &vi->guest_offloads);
2653+
25942654
pr_debug("virtnet: registered device %s with %d RX and TX vq's\n",
25952655
dev->name, max_queue_pairs);
25962656

@@ -2687,7 +2747,7 @@ static struct virtio_device_id id_table[] = {
26872747
VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN, \
26882748
VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, \
26892749
VIRTIO_NET_F_CTRL_MAC_ADDR, \
2690-
VIRTIO_NET_F_MTU
2750+
VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS
26912751

26922752
static unsigned int features[] = {
26932753
VIRTNET_FEATURES,

0 commit comments

Comments
 (0)