Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164562104
D27916.id82542.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D27916.id82542.diff
View Options
diff --git a/sys/dev/virtio/network/if_vtnet.c b/sys/dev/virtio/network/if_vtnet.c
--- a/sys/dev/virtio/network/if_vtnet.c
+++ b/sys/dev/virtio/network/if_vtnet.c
@@ -193,6 +193,7 @@
static int vtnet_init_tx_queues(struct vtnet_softc *);
static int vtnet_init_rxtx_queues(struct vtnet_softc *);
static void vtnet_set_active_vq_pairs(struct vtnet_softc *);
+static void vtnet_update_rx_offloads(struct vtnet_softc *);
static int vtnet_reinit(struct vtnet_softc *);
static void vtnet_init_locked(struct vtnet_softc *, int);
static void vtnet_init(void *);
@@ -201,6 +202,7 @@
static void vtnet_exec_ctrl_cmd(struct vtnet_softc *, void *,
struct sglist *, int, int);
static int vtnet_ctrl_mac_cmd(struct vtnet_softc *, uint8_t *);
+static int vtnet_ctrl_guest_offloads(struct vtnet_softc *, uint64_t);
static int vtnet_ctrl_mq_cmd(struct vtnet_softc *, uint16_t);
static int vtnet_ctrl_rx_cmd(struct vtnet_softc *, uint8_t, int);
static int vtnet_set_promisc(struct vtnet_softc *, int);
@@ -1045,7 +1047,11 @@
}
if (virtio_with_feature(dev, VIRTIO_NET_F_GUEST_CSUM)) {
- ifp->if_capabilities |= IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6;
+ ifp->if_capabilities |= IFCAP_RXCSUM;
+#ifdef notyet
+ /* BMV: Rx checksums not distinguished between IPv4 and IPv6. */
+ ifp->if_capabilities |= IFCAP_RXCSUM_IPV6;
+#endif
if (vtnet_tunable_int(sc, "fixup_needs_csum",
vtnet_fixup_needs_csum) != 0)
@@ -1215,10 +1221,11 @@
vtnet_ioctl_ifcap(struct vtnet_softc *sc, struct ifreq *ifr)
{
struct ifnet *ifp;
- int mask, reinit;
+ int mask, reinit, update;
ifp = sc->vtnet_ifp;
mask = (ifr->ifr_reqcap & ifp->if_capabilities) ^ ifp->if_capenable;
+ reinit = update = 0;
VTNET_CORE_LOCK_ASSERT(sc);
@@ -1231,10 +1238,15 @@
if (mask & IFCAP_TSO6)
ifp->if_capenable ^= IFCAP_TSO6;
- if (mask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6 | IFCAP_LRO |
- IFCAP_VLAN_HWFILTER)) {
- /* These Rx features require us to renegotiate. */
- reinit = 1;
+ if (mask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6 | IFCAP_LRO)) {
+ /*
+ * These Rx features require the negotiated features to
+ * be updated. Avoid a full reinit if possible.
+ */
+ if (sc->vtnet_features & VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)
+ update = 1;
+ else
+ reinit = 1;
if (mask & IFCAP_RXCSUM)
ifp->if_capenable ^= IFCAP_RXCSUM;
@@ -1242,19 +1254,41 @@
ifp->if_capenable ^= IFCAP_RXCSUM_IPV6;
if (mask & IFCAP_LRO)
ifp->if_capenable ^= IFCAP_LRO;
+
+ /*
+ * VirtIO does not distinguish between IPv4 and IPv6 checksums
+ * so treat them as a pair. Guest TSO (LRO) requires receive
+ * checksums.
+ */
+ if (ifp->if_capenable & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) {
+ ifp->if_capenable |= IFCAP_RXCSUM;
+#ifdef notyet
+ ifp->if_capenable |= IFCAP_RXCSUM_IPV6;
+#endif
+ } else
+ ifp->if_capenable &=
+ ~(IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6 | IFCAP_LRO);
+ }
+
+ if (mask & IFCAP_VLAN_HWFILTER) {
+ /* These Rx features require renegotiation. */
+ reinit = 1;
+
if (mask & IFCAP_VLAN_HWFILTER)
ifp->if_capenable ^= IFCAP_VLAN_HWFILTER;
- } else
- reinit = 0;
+ }
if (mask & IFCAP_VLAN_HWTSO)
ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
if (mask & IFCAP_VLAN_HWTAGGING)
ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
- if (reinit && (ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- vtnet_init_locked(sc, 0);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ if (reinit) {
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ vtnet_init_locked(sc, 0);
+ } else if (update)
+ vtnet_update_rx_offloads(sc);
}
return (0);
@@ -3023,28 +3057,14 @@
* via if_capenable and if_hwassist.
*/
- if (ifp->if_capabilities & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) {
- /*
- * VirtIO does not distinguish between the IPv4 and IPv6
- * checksums so require both. Guest TSO (LRO) requires
- * Rx checksums.
- */
- if ((ifp->if_capenable &
- (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) == 0) {
- features &= ~VIRTIO_NET_F_GUEST_CSUM;
- features &= ~VTNET_LRO_FEATURES;
- }
- }
+ if ((ifp->if_capenable & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) == 0)
+ features &= ~(VIRTIO_NET_F_GUEST_CSUM | VTNET_LRO_FEATURES);
- if (ifp->if_capabilities & IFCAP_LRO) {
- if ((ifp->if_capenable & IFCAP_LRO) == 0)
- features &= ~VTNET_LRO_FEATURES;
- }
+ if ((ifp->if_capenable & IFCAP_LRO) == 0)
+ features &= ~VTNET_LRO_FEATURES;
- if (ifp->if_capabilities & IFCAP_VLAN_HWFILTER) {
- if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0)
- features &= ~VIRTIO_NET_F_CTRL_VLAN;
- }
+ if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0)
+ features &= ~VIRTIO_NET_F_CTRL_VLAN;
error = virtio_reinit(dev, features);
if (error) {
@@ -3172,6 +3192,47 @@
sc->vtnet_act_vq_pairs = npairs;
}
+static void
+vtnet_update_rx_offloads(struct vtnet_softc *sc)
+{
+ struct ifnet *ifp;
+ uint64_t features;
+ int error;
+
+ ifp = sc->vtnet_ifp;
+ features = sc->vtnet_features;
+
+ VTNET_CORE_LOCK_ASSERT(sc);
+
+ if (ifp->if_capabilities & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) {
+ if (ifp->if_capenable & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6))
+ features |= VIRTIO_NET_F_GUEST_CSUM;
+ else
+ features &= ~VIRTIO_NET_F_GUEST_CSUM;
+ }
+
+ if (ifp->if_capabilities & IFCAP_LRO) {
+ if (ifp->if_capenable & IFCAP_LRO)
+ features |= VTNET_LRO_FEATURES;
+ else
+ features &= ~VTNET_LRO_FEATURES;
+ }
+
+ error = vtnet_ctrl_guest_offloads(sc,
+ features & (VIRTIO_NET_F_GUEST_CSUM | VIRTIO_NET_F_GUEST_TSO4 |
+ VIRTIO_NET_F_GUEST_TSO6 | VIRTIO_NET_F_GUEST_ECN |
+ VIRTIO_NET_F_GUEST_UFO));
+ if (error) {
+ device_printf(sc->vtnet_dev,
+ "%s: cannot update Rx features\n", __func__);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ vtnet_init_locked(sc, 0);
+ }
+ } else
+ sc->vtnet_features = features;
+}
+
static int
vtnet_reinit(struct vtnet_softc *sc)
{
@@ -3337,6 +3398,40 @@
return (s.ack == VIRTIO_NET_OK ? 0 : EIO);
}
+static int
+vtnet_ctrl_guest_offloads(struct vtnet_softc *sc, uint64_t offloads)
+{
+ struct sglist_seg segs[3];
+ struct sglist sg;
+ struct {
+ struct virtio_net_ctrl_hdr hdr __aligned(2);
+ uint8_t pad1;
+ uint64_t offloads __aligned(8);
+ uint8_t pad2;
+ uint8_t ack;
+ } s;
+ int error;
+
+ error = 0;
+ MPASS(sc->vtnet_features & VIRTIO_NET_F_CTRL_GUEST_OFFLOADS);
+
+ s.hdr.class = VIRTIO_NET_CTRL_GUEST_OFFLOADS;
+ s.hdr.cmd = VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET;
+ s.offloads = vtnet_gtoh64(sc, offloads);
+ s.ack = VIRTIO_NET_ERR;
+
+ sglist_init(&sg, nitems(segs), segs);
+ error |= sglist_append(&sg, &s.hdr, sizeof(struct virtio_net_ctrl_hdr));
+ error |= sglist_append(&sg, &s.offloads, sizeof(uint64_t));
+ error |= sglist_append(&sg, &s.ack, sizeof(uint8_t));
+ MPASS(error == 0 && sg.sg_nseg == nitems(segs));
+
+ if (error == 0)
+ vtnet_exec_ctrl_cmd(sc, &s.ack, &sg, sg.sg_nseg - 1, 1);
+
+ return (s.ack == VIRTIO_NET_OK ? 0 : EIO);
+}
+
static int
vtnet_ctrl_mq_cmd(struct vtnet_softc *sc, uint16_t npairs)
{
diff --git a/sys/dev/virtio/network/if_vtnetvar.h b/sys/dev/virtio/network/if_vtnetvar.h
--- a/sys/dev/virtio/network/if_vtnetvar.h
+++ b/sys/dev/virtio/network/if_vtnetvar.h
@@ -293,6 +293,7 @@
#define VTNET_COMMON_FEATURES \
(VIRTIO_NET_F_MAC | \
VIRTIO_NET_F_STATUS | \
+ VIRTIO_NET_F_CTRL_GUEST_OFFLOADS | \
VIRTIO_NET_F_MTU | \
VIRTIO_NET_F_CTRL_VQ | \
VIRTIO_NET_F_CTRL_RX | \
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Aug 3, 2:47 AM (19 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35858638
Default Alt Text
D27916.id82542.diff (7 KB)
Attached To
Mode
D27916: if_vtnet: Add support for CTRL_GUEST_OFFLOADS feature
Attached
Detach File
Event Timeline
Log In to Comment