svn commit: r249325 - user/bryanv/vtnetmq/sys/dev/virtio/network
Bryan Venteicher
bryanv at FreeBSD.org
Wed Apr 10 06:21:40 UTC 2013
Author: bryanv
Date: Wed Apr 10 06:21:39 2013
New Revision: 249325
URL: http://svnweb.freebsd.org/changeset/base/249325
Log:
Commit development snapshot of the multiqueue driver
This commit includes various (mostly minor) changes:
- Support for instance specific and global tunables
- Fix a swap argument bug that broke TSO
- Initial support for the VIRTIO_NET_F_CTRL_MAC_ADDR feature
- Shuffle some structure around to be more cache line friendly
Modified:
user/bryanv/vtnetmq/sys/dev/virtio/network/if_vtnet.c
user/bryanv/vtnetmq/sys/dev/virtio/network/if_vtnetvar.h
user/bryanv/vtnetmq/sys/dev/virtio/network/virtio_net.h
Modified: user/bryanv/vtnetmq/sys/dev/virtio/network/if_vtnet.c
==============================================================================
--- user/bryanv/vtnetmq/sys/dev/virtio/network/if_vtnet.c Wed Apr 10 05:59:07 2013 (r249324)
+++ user/bryanv/vtnetmq/sys/dev/virtio/network/if_vtnet.c Wed Apr 10 06:21:39 2013 (r249325)
@@ -175,6 +175,7 @@ static void vtnet_init(void *);
static void vtnet_free_ctrl_vq(struct vtnet_softc *);
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_mq_cmd(struct vtnet_softc *, uint16_t);
static int vtnet_ctrl_rx_cmd(struct vtnet_softc *, int, int);
static int vtnet_set_promisc(struct vtnet_softc *, int);
@@ -214,6 +215,8 @@ static void vtnet_disable_rx_interrupts(
static void vtnet_disable_tx_interrupts(struct vtnet_softc *);
static void vtnet_disable_interrupts(struct vtnet_softc *);
+static int vtnet_tunable_int(struct vtnet_softc *, const char *, int);
+
/* Tunables. */
static int vtnet_csum_disable = 0;
TUNABLE_INT("hw.vtnet.csum_disable", &vtnet_csum_disable);
@@ -222,10 +225,10 @@ TUNABLE_INT("hw.vtnet.tso_disable", &vtn
static int vtnet_lro_disable = 0;
TUNABLE_INT("hw.vtnet.lro_disable", &vtnet_lro_disable);
static int vtnet_mq_disable = 0;
-TUNABLE_INT("hw.vtnet.mq_dislabe", &vtnet_mq_disable);
-static int vtnet_mq_max_queues = 0;
-TUNABLE_INT("hw.vtnet.mq_max_queues", &vtnet_mq_max_queues);
-static int vtnet_rx_process_limit = 256;
+TUNABLE_INT("hw.vtnet.mq_disable", &vtnet_mq_disable);
+static int vtnet_mq_max_pairs = 0;
+TUNABLE_INT("hw.vtnet.mq_max_pairs", &vtnet_mq_max_pairs);
+static int vtnet_rx_process_limit = 512;
TUNABLE_INT("hw.vtnet.rx_process_limit", &vtnet_rx_process_limit);
/*
@@ -519,13 +522,15 @@ vtnet_negotiate_features(struct vtnet_so
* TSO and LRO are only available when their corresponding checksum
* offload feature is also negotiated.
*/
- if (vtnet_csum_disable)
+ if (vtnet_tunable_int(sc, "csum_disable", vtnet_csum_disable)) {
mask |= VIRTIO_NET_F_CSUM | VIRTIO_NET_F_GUEST_CSUM;
- if (vtnet_csum_disable || vtnet_tso_disable)
+ mask |= VTNET_TSO_FEATURES | VTNET_LRO_FEATURES;
+ }
+ if (vtnet_tunable_int(sc, "tso_disable", vtnet_tso_disable))
mask |= VTNET_TSO_FEATURES;
- if (vtnet_csum_disable || vtnet_lro_disable)
+ if (vtnet_tunable_int(sc, "lro_disable", vtnet_lro_disable))
mask |= VTNET_LRO_FEATURES;
- if (vtnet_mq_disable)
+ if (vtnet_tunable_int(sc, "mq_disable", vtnet_mq_disable))
mask |= VIRTIO_NET_F_MQ;
features = VTNET_FEATURES & ~mask;
@@ -559,12 +564,17 @@ static void
vtnet_setup_features(struct vtnet_softc *sc)
{
device_t dev;
- int max_pairs;
+ int max_pairs, max;
dev = sc->vtnet_dev;
vtnet_negotiate_features(sc);
+ if (virtio_with_feature(dev, VIRTIO_NET_F_MAC)) {
+ /* This feature should always be negotiated. */
+ sc->vtnet_flags |= VTNET_FLAG_MAC;
+ }
+
if (virtio_with_feature(dev, VIRTIO_NET_F_MRG_RXBUF)) {
sc->vtnet_flags |= VTNET_FLAG_MRG_RXBUFS;
sc->vtnet_hdr_size = sizeof(struct virtio_net_hdr_mrg_rxbuf);
@@ -578,6 +588,8 @@ vtnet_setup_features(struct vtnet_softc
sc->vtnet_flags |= VTNET_FLAG_CTRL_RX;
if (virtio_with_feature(dev, VIRTIO_NET_F_CTRL_VLAN))
sc->vtnet_flags |= VTNET_FLAG_VLAN_FILTER;
+ if (virtio_with_feature(dev, VIRTIO_NET_F_CTRL_MAC_ADDR))
+ sc->vtnet_flags |= VTNET_FLAG_CTRL_MAC;
}
if (virtio_with_feature(dev, VIRTIO_NET_F_MQ) &&
@@ -592,16 +604,17 @@ vtnet_setup_features(struct vtnet_softc
if (max_pairs > 1) {
/*
- * Limit the maximum number of queue pairs to the number
- * of CPUs or the configured maximum. The actual number
- * of queues that get used may be less.
+ * Limit the maximum number of queue pairs to the number of
+ * CPUs or the configured maximum. The actual number of
+ * queues that get used may be less.
*/
+ max = vtnet_tunable_int(sc, "mq_max_pairs", vtnet_mq_max_pairs);
+ if (max > 0 && max_pairs > max)
+ max_pairs = max;
if (max_pairs > mp_ncpus)
max_pairs = mp_ncpus;
if (max_pairs > VTNET_MAX_QUEUE_PAIRS)
max_pairs = VTNET_MAX_QUEUE_PAIRS;
- if (vtnet_mq_max_queues != 0)
- max_pairs = vtnet_mq_max_queues;
if (max_pairs > 1)
sc->vtnet_flags |= VTNET_FLAG_MULTIQ;
}
@@ -622,7 +635,6 @@ vtnet_init_rxq(struct vtnet_softc *sc, i
rxq->vtnrx_sc = sc;
rxq->vtnrx_id = id;
- rxq->vtnrx_process_limit = vtnet_rx_process_limit;
TASK_INIT(&rxq->vtnrx_intrtask, 0, vtnet_rxq_tq_intr, rxq);
rxq->vtnrx_tq = taskqueue_create(rxq->vtnrx_name, M_NOWAIT,
@@ -708,10 +720,12 @@ vtnet_destroy_txq(struct vtnet_txq *txq)
txq->vtntx_sc = NULL;
txq->vtntx_id = -1;
+#ifndef VTNET_LEGACY_TX
if (txq->vtntx_br != NULL) {
buf_ring_free(txq->vtntx_br, M_DEVBUF);
txq->vtntx_br = NULL;
}
+#endif
if (mtx_initialized(&txq->vtntx_mtx) != 0)
mtx_destroy(&txq->vtntx_mtx);
@@ -1035,35 +1049,15 @@ vtnet_ioctl(struct ifnet *ifp, u_long cm
VTNET_CORE_LOCK(sc);
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
- if (mask & IFCAP_TXCSUM) {
+ if (mask & IFCAP_TXCSUM)
ifp->if_capenable ^= IFCAP_TXCSUM;
- if (ifp->if_capenable & IFCAP_TXCSUM)
- ifp->if_hwassist |= VTNET_CSUM_OFFLOAD;
- else
- ifp->if_hwassist &= ~VTNET_CSUM_OFFLOAD;
- }
-
- if (mask & IFCAP_TXCSUM_IPV6) {
+ if (mask & IFCAP_TXCSUM_IPV6)
ifp->if_capenable ^= IFCAP_TXCSUM_IPV6;
- if (ifp->if_capenable & IFCAP_TXCSUM_IPV6)
- ifp->if_hwassist |= VTNET_CSUM_OFFLOAD_IPV6;
- else
- ifp->if_hwassist &= ~VTNET_CSUM_OFFLOAD_IPV6;
- }
-
if (mask & IFCAP_TSO) {
if (mask & IFCAP_TSO4)
ifp->if_capenable ^= IFCAP_TSO4;
if (mask & IFCAP_TSO6)
ifp->if_capenable ^= IFCAP_TSO6;
- /*
- * Set if either is enabled. The CSUM_TSO_IPV6 flag is
- * currently commented out.
- */
- if (ifp->if_capenable & IFCAP_TSO)
- ifp->if_hwassist |= CSUM_TSO;
- else
- ifp->if_hwassist &= ~CSUM_TSO;
}
if (mask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6 | IFCAP_LRO |
@@ -1423,10 +1417,10 @@ vtnet_rxq_csum_by_offset(struct vtnet_rx
}
/*
- * Use the offset to determine the appropriate CSUM_* flags. This
- * is a bit dirty, but we can get by with it since the checksum
- * offsets happen to be different. We assume the host host does
- * not do IPv4 header checksum offloading.
+ * Use the offset to determine the appropriate CSUM_* flags. This is
+ * a bit dirty, but we can get by with it since the checksum offsets
+ * happen to be different. We assume the host host does not do IPv4
+ * header checksum offloading.
*/
switch (hdr->csum_offset) {
case offsetof(struct udphdr, uh_sum):
@@ -1648,7 +1642,7 @@ vtnet_rxq_input(struct vtnet_rxq *rxq, s
m->m_flags |= M_FLOWID;
/*
- * BVM: FreeBSD does not have the UNNECESSARY and PARTIAL checksum
+ * BMV: FreeBSD does not have the UNNECESSARY and PARTIAL checksum
* distinction that Linux does. Need to reevaluate if performing
* offloading for the NEEDS_CSUM case is really appropriate.
*/
@@ -1686,7 +1680,7 @@ vtnet_rxq_eof(struct vtnet_rxq *rxq)
hdr = &lhdr;
deq = 0;
- count = rxq->vtnrx_process_limit;
+ count = sc->vtnet_rx_process_limit;
VTNET_RXQ_LOCK_ASSERT(rxq);
@@ -1962,7 +1956,7 @@ vtnet_txq_offload(struct vtnet_txq *txq,
sc = txq->vtntx_sc;
flags = m->m_pkthdr.csum_flags;
- error = vtnet_txq_offload_ctx(txq, m, &etype, &csum_start, &proto);
+ error = vtnet_txq_offload_ctx(txq, m, &etype, &proto, &csum_start);
if (error)
goto drop;
@@ -2695,7 +2689,7 @@ vtnet_virtio_reinit(struct vtnet_softc *
if (ifp->if_capabilities & _RXCSUM_IPV46) {
/*
* We require both IPv4 and IPv6 offloading to be enabled
- * inorder to negotiated it: VirtIO does not distinguish
+ * in order to negotiated it: VirtIO does not distinguish
* between the two.
*
* BMV: What about when INET and/or INET6 is not defined?
@@ -2736,7 +2730,6 @@ vtnet_init_rx_filters(struct vtnet_softc
vtnet_rx_filter_mac(sc);
}
- /* Restore filtered VLANs. */
if (ifp->if_capenable & IFCAP_VLAN_HWFILTER)
vtnet_rx_filter_vlan(sc);
}
@@ -2746,11 +2739,21 @@ vtnet_init_rx_queues(struct vtnet_softc
{
device_t dev;
struct vtnet_rxq *rxq;
- int i, clsize, error;
+ int i, limit, clsize, error;
dev = sc->vtnet_dev;
/*
+ * Assume the same limit is appropriate for all the Rx queues.
+ * We may later want to scale this by each virtqueue's size.
+ */
+ limit = vtnet_tunable_int(sc, "rx_process_limit",
+ vtnet_rx_process_limit);
+ if (limit < 0)
+ limit = INT_MAX;
+ sc->vtnet_rx_process_limit = limit;
+
+ /*
* Use the new cluster size if one has been set (via a MTU
* change). Otherwise, use the standard 2K clusters.
*
@@ -2974,6 +2977,32 @@ vtnet_exec_ctrl_cmd(struct vtnet_softc *
}
static int
+vtnet_ctrl_mac_cmd(struct vtnet_softc *sc, uint8_t *hwaddr)
+{
+ struct virtio_net_ctrl_hdr hdr;
+ struct sglist_seg segs[3];
+ struct sglist sg;
+ uint8_t ack;
+ int error;
+
+ hdr.class = VIRTIO_NET_CTRL_MAC;
+ hdr.cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET;
+ ack = VIRTIO_NET_ERR;
+
+ sglist_init(&sg, 3, segs);
+ error = 0;
+ error |= sglist_append(&sg, &hdr, sizeof(struct virtio_net_ctrl_hdr));
+ error |= sglist_append(&sg, hwaddr, ETHER_ADDR_LEN);
+ error |= sglist_append(&sg, &ack, sizeof(uint8_t));
+ KASSERT(error == 0 && sg.sg_nseg == 3,
+ ("%s: error %d adding set MAC msg to sglist", __func__, error));
+
+ vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg - 1, 1);
+
+ return (ack == VIRTIO_NET_OK ? 0 : EIO);
+}
+
+static int
vtnet_ctrl_mq_cmd(struct vtnet_softc *sc, uint16_t npairs)
{
struct sglist_seg segs[3];
@@ -2987,9 +3016,6 @@ vtnet_ctrl_mq_cmd(struct vtnet_softc *sc
} s;
int error;
- if ((sc->vtnet_flags & VTNET_FLAG_CTRL_VQ) == 0)
- return (ENOTSUP);
-
s.hdr.class = VIRTIO_NET_CTRL_MQ;
s.hdr.cmd = VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET;
s.mq.virtqueue_pairs = npairs;
@@ -3204,12 +3230,10 @@ vtnet_rx_filter_mac(struct vtnet_softc *
if_printf(ifp, "error setting host MAC filter table\n");
out:
- if (promisc)
- if (vtnet_set_promisc(sc, 1) != 0)
- if_printf(ifp, "cannot enable promiscuous mode\n");
- if (allmulti)
- if (vtnet_set_allmulti(sc, 1) != 0)
- if_printf(ifp, "cannot enable all-multicast mode\n");
+ if (promisc && vtnet_set_promisc(sc, 1) != 0)
+ if_printf(ifp, "cannot enable promiscuous mode\n");
+ if (allmulti && vtnet_set_allmulti(sc, 1) != 0)
+ if_printf(ifp, "cannot enable all-multicast mode\n");
}
static int
@@ -3286,11 +3310,6 @@ vtnet_update_vlan_filter(struct vtnet_so
VTNET_CORE_LOCK(sc);
- /*
- * Update the in-memory table. We must keep the table current with
- * configured VLANs even if HW filtering is disabled, since it could
- * be enabled later.
- */
if (add)
sc->vtnet_vlan_filter[idx] |= (1 << bit);
else
@@ -3407,8 +3426,14 @@ vtnet_set_hwaddr(struct vtnet_softc *sc)
dev = sc->vtnet_dev;
- virtio_write_device_config(dev, offsetof(struct virtio_net_config, mac),
- sc->vtnet_hwaddr, ETHER_ADDR_LEN);
+ if (sc->vtnet_flags & VTNET_FLAG_CTRL_MAC) {
+ if (vtnet_ctrl_mac_cmd(sc, sc->vtnet_hwaddr) != 0)
+ device_printf(dev, "unable to set MAC address\n");
+ } else if (sc->vtnet_flags & VTNET_FLAG_MAC) {
+ virtio_write_device_config(dev,
+ offsetof(struct virtio_net_config, mac),
+ sc->vtnet_hwaddr, ETHER_ADDR_LEN);
+ }
}
static void
@@ -3418,7 +3443,7 @@ vtnet_get_hwaddr(struct vtnet_softc *sc)
dev = sc->vtnet_dev;
- if (virtio_with_feature(dev, VIRTIO_NET_F_MAC) == 0) {
+ if ((sc->vtnet_flags & VTNET_FLAG_MAC) == 0) {
/*
* Generate a random locally administered unicast address.
*
@@ -3707,3 +3732,15 @@ vtnet_disable_interrupts(struct vtnet_so
vtnet_disable_rx_interrupts(sc);
vtnet_disable_tx_interrupts(sc);
}
+
+static int
+vtnet_tunable_int(struct vtnet_softc *sc, const char *knob, int def)
+{
+ char path[64];
+
+ snprintf(path, sizeof(path),
+ "hw.vtnet.%d.%s", device_get_unit(sc->vtnet_dev), knob);
+ TUNABLE_INT_FETCH(path, &def);
+
+ return (def);
+}
Modified: user/bryanv/vtnetmq/sys/dev/virtio/network/if_vtnetvar.h
==============================================================================
--- user/bryanv/vtnetmq/sys/dev/virtio/network/if_vtnetvar.h Wed Apr 10 05:59:07 2013 (r249324)
+++ user/bryanv/vtnetmq/sys/dev/virtio/network/if_vtnetvar.h Wed Apr 10 06:21:39 2013 (r249325)
@@ -100,7 +100,9 @@ struct vtnet_txq {
struct mtx vtntx_mtx;
struct vtnet_softc *vtntx_sc;
struct virtqueue *vtntx_vq;
+#ifndef VTNET_LEGACY_TX
struct buf_ring *vtntx_br;
+#endif
int vtntx_id;
int vtntx_watchdog;
struct vtnet_txq_stats vtntx_stats;
@@ -123,43 +125,45 @@ struct vtnet_txq {
struct vtnet_softc {
device_t vtnet_dev;
struct ifnet *vtnet_ifp;
- struct mtx vtnet_mtx;
+ struct vtnet_rxq *vtnet_rxqs;
+ struct vtnet_txq *vtnet_txqs;
uint32_t vtnet_flags;
#define VTNET_FLAG_SUSPENDED 0x0001
-#define VTNET_FLAG_CTRL_VQ 0x0002
-#define VTNET_FLAG_CTRL_RX 0x0004
-#define VTNET_FLAG_VLAN_FILTER 0x0008
-#define VTNET_FLAG_TSO_ECN 0x0010
-#define VTNET_FLAG_MRG_RXBUFS 0x0020
-#define VTNET_FLAG_LRO_NOMRG 0x0040
-#define VTNET_FLAG_MULTIQ 0x0080
-
- struct vtnet_rxq *vtnet_rxqs;
- struct vtnet_txq *vtnet_txqs;
- struct virtqueue *vtnet_ctrl_vq;
+#define VTNET_FLAG_MAC 0x0002
+#define VTNET_FLAG_CTRL_VQ 0x0004
+#define VTNET_FLAG_CTRL_RX 0x0008
+#define VTNET_FLAG_CTRL_MAC 0x0010
+#define VTNET_FLAG_VLAN_FILTER 0x0020
+#define VTNET_FLAG_TSO_ECN 0x0040
+#define VTNET_FLAG_MRG_RXBUFS 0x0080
+#define VTNET_FLAG_LRO_NOMRG 0x0100
+#define VTNET_FLAG_MULTIQ 0x0200
- int vtnet_hdr_size;
int vtnet_link_active;
+ int vtnet_hdr_size;
+ int vtnet_rx_process_limit;
int vtnet_rx_nmbufs;
int vtnet_rx_clsize;
int vtnet_rx_new_clsize;
int vtnet_if_flags;
int vtnet_act_vq_pairs;
int vtnet_max_vq_pairs;
- uint64_t vtnet_features;
-
- struct vtnet_statistics vtnet_stats;
- struct callout vtnet_tick_ch;
+ struct virtqueue *vtnet_ctrl_vq;
struct vtnet_mac_filter *vtnet_mac_filter;
uint32_t *vtnet_vlan_filter;
+
+ uint64_t vtnet_features;
+ struct vtnet_statistics vtnet_stats;
+ struct callout vtnet_tick_ch;
struct ifmedia vtnet_media;
eventhandler_tag vtnet_vlan_attach;
eventhandler_tag vtnet_vlan_detach;
- char vtnet_hwaddr[ETHER_ADDR_LEN];
+ struct mtx vtnet_mtx;
char vtnet_mtx_name[16];
+ char vtnet_hwaddr[ETHER_ADDR_LEN];
};
/*
@@ -181,8 +185,8 @@ struct vtnet_softc {
#define VTNET_MEDIATYPE (IFM_ETHER | IFM_10G_T | IFM_FDX)
/*
- * Number of words to allocate for the VLAN shadow table. Each possible
- * VLAN gets one bit.
+ * Number of words to allocate for the VLAN shadow table. There is one
+ * bit for each VLAN.
*/
#define VTNET_VLAN_FILTER_NWORDS (4096 / 32)
@@ -263,7 +267,6 @@ CTASSERT(sizeof(struct vtnet_mac_filter)
VIRTIO_NET_F_GUEST_TSO6 | \
VIRTIO_NET_F_GUEST_ECN | \
VIRTIO_NET_F_MRG_RXBUF | \
- VIRTIO_NET_F_MQ | \
VIRTIO_RING_F_INDIRECT_DESC)
/*
Modified: user/bryanv/vtnetmq/sys/dev/virtio/network/virtio_net.h
==============================================================================
--- user/bryanv/vtnetmq/sys/dev/virtio/network/virtio_net.h Wed Apr 10 05:59:07 2013 (r249324)
+++ user/bryanv/vtnetmq/sys/dev/virtio/network/virtio_net.h Wed Apr 10 06:21:39 2013 (r249325)
@@ -51,7 +51,8 @@
#define VIRTIO_NET_F_CTRL_VLAN 0x80000 /* Control channel VLAN filtering */
#define VIRTIO_NET_F_CTRL_RX_EXTRA 0x100000 /* Extra RX mode control support */
#define VIRTIO_NET_F_GUEST_ANNOUNCE 0x200000 /* Announce device on network */
-#define VIRTIO_NET_F_MQ 0x400000
+#define VIRTIO_NET_F_MQ 0x400000 /* Device supports RFS */
+#define VIRTIO_NET_F_CTRL_MAC_ADDR 0x800000 /* Set MAC address */
#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */
@@ -142,6 +143,10 @@ typedef uint8_t virtio_net_ctrl_ack;
* first sg list contains unicast addresses, the second is for multicast.
* This functionality is present if the VIRTIO_NET_F_CTRL_RX feature
* is available.
+ *
+ * The ADDR_SET command requests one out scatterlist, it contains a
+ * 6 bytes MAC address. This functionality is present if the
+ * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available.
*/
struct virtio_net_ctrl_mac {
uint32_t entries;
@@ -150,6 +155,7 @@ struct virtio_net_ctrl_mac {
#define VIRTIO_NET_CTRL_MAC 1
#define VIRTIO_NET_CTRL_MAC_TABLE_SET 0
+#define VIRTIO_NET_CTRL_MAC_ADDR_SET 1
/*
* Control VLAN filtering
More information about the svn-src-user
mailing list