Page MenuHomeFreeBSD

D21315.id.diff
No OneTemporary

D21315.id.diff

Index: usr.sbin/bhyve/net_backends.c
===================================================================
--- usr.sbin/bhyve/net_backends.c
+++ usr.sbin/bhyve/net_backends.c
@@ -46,6 +46,7 @@
#include <sys/uio.h>
#include <net/if.h>
+#include <net/if_tap.h>
#include <net/netmap.h>
#include <net/netmap_virt.h>
#define NETMAP_WITH_LIBS
@@ -158,14 +159,97 @@
#define WPRINTF(params) printf params
+/*
+ * The virtio-net features supported by the tap and netmap
+ * backends.
+ */
+#define NETMAP_FEATURES (VIRTIO_NET_F_CSUM | VIRTIO_NET_F_HOST_TSO4 | \
+ VIRTIO_NET_F_HOST_TSO6 | VIRTIO_NET_F_HOST_UFO | \
+ VIRTIO_NET_F_GUEST_CSUM | VIRTIO_NET_F_GUEST_TSO4 | \
+ VIRTIO_NET_F_GUEST_TSO6 | VIRTIO_NET_F_GUEST_UFO | \
+ VIRTIO_NET_F_MRG_RXBUF)
+#define TAP_FEATURES NETMAP_FEATURES
+
/*
* The tap backend
*/
struct tap_priv {
+ char ifname[IFNAMSIZ];
struct mevent *mevp;
};
+#define TAP_VHDR_IFCAPS (IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6 \
+ | IFCAP_VLAN_HWCSUM | IFCAP_TSO \
+ | IFCAP_LRO | IFCAP_VLAN_HWTSO)
+
+static int
+tap_set_vnet_hdr_len(struct net_backend *be, unsigned vnet_hdr_len)
+{
+ struct tap_priv *priv = (struct tap_priv *)be->opaque;
+ int ival = vnet_hdr_len;
+ struct ifreq ifreq;
+ int ret;
+ int s;
+
+ /*
+ * Configure the virtio-net header length, using the tap(4) character
+ * device interface.
+ */
+ ret = ioctl(be->fd, TAPSVNETHDR, &ival);
+ if (ret) {
+ WPRINTF(("ioctl(TAPSVNETHDR) failed: %s\n",
+ strerror(errno)));
+ return (ret);
+ }
+
+ /*
+ * Open a socket to run ioctl() commands on the tap(4) network
+ * interface.
+ */
+ s = socket(AF_LOCAL, SOCK_DGRAM, 0);
+ if (s < 0) {
+ WPRINTF(("socket(AF_LOCAL) failed: %s\n", strerror(errno)));
+ return (s);
+ }
+
+ /*
+ * Get interface capabilities: enabled capabilities are stored
+ * in ifreq.ifr_curcap, while supported ones are stored in
+ * ifreq.ifr_reqcap.
+ */
+ memset(&ifreq, 0, sizeof(ifreq));
+ strlcpy(ifreq.ifr_name, priv->ifname, sizeof(ifreq.ifr_name));
+
+ ret = ioctl(s, SIOCGIFCAP, &ifreq);
+ if (ret) {
+ WPRINTF(("ioctl(SIOCGIFCAP) failed: %s\n", strerror(errno)));
+ close(s);
+ return (ret);
+ }
+
+ /*
+ * Enable or disable tap(4) capabilities for TX/RX checksum and
+ * TSO/LRO.
+ */
+ if (vnet_hdr_len != 0) {
+ assert((ifreq.ifr_reqcap & TAP_VHDR_IFCAPS) == TAP_VHDR_IFCAPS);
+ ifreq.ifr_reqcap = ifreq.ifr_curcap | TAP_VHDR_IFCAPS;
+ } else {
+ ifreq.ifr_reqcap = ifreq.ifr_curcap & (~TAP_VHDR_IFCAPS);
+ }
+ ret = ioctl(s, SIOCSIFCAP, &ifreq);
+ if (ret) {
+ WPRINTF(("ioctl(SIOCSIFCAP) failed: %s\n", strerror(errno)));
+ close(s);
+ return (ret);
+ }
+
+ close(s);
+
+ return (0);
+}
+
static void
tap_cleanup(struct net_backend *be)
{
@@ -196,6 +280,11 @@
return (-1);
}
+ if (strlcpy(priv->ifname, devname, sizeof(priv->ifname)) >=
+ sizeof(priv->ifname)) {
+ WPRINTF(("TAP device name too long\n"));
+ return (-1);
+ }
strcpy(tbuf, "/dev/");
strlcat(tbuf, devname, sizeof(tbuf));
@@ -215,7 +304,7 @@
}
#ifndef WITHOUT_CAPSICUM
- cap_rights_init(&rights, CAP_EVENT, CAP_READ, CAP_WRITE);
+ cap_rights_init(&rights, CAP_EVENT, CAP_READ, CAP_WRITE, CAP_IOCTL);
if (caph_rights_limit(be->fd, &rights) == -1)
errx(EX_OSERR, "Unable to apply rights for sandbox");
#endif
@@ -278,16 +367,35 @@
static uint64_t
tap_get_cap(struct net_backend *be)
{
+ int ret;
- return (0); /* no capabilities for now */
+ /*
+ * Check if we are able to set the virtio net header.
+ * If we are not, we tell the caller that we do not support
+ * any offload.
+ */
+ if (tap_set_vnet_hdr_len(be, sizeof(struct virtio_net_rxhdr))) {
+ return (0);
+ }
+
+ ret = tap_set_vnet_hdr_len(be, 0);
+ assert(ret == 0);
+
+ return (TAP_FEATURES);
}
static int
tap_set_cap(struct net_backend *be, uint64_t features,
unsigned vnet_hdr_len)
{
+ int ret;
- return ((features || vnet_hdr_len) ? -1 : 0);
+ ret = tap_set_vnet_hdr_len(be, vnet_hdr_len);
+ assert(ret == 0);
+
+ be->be_vnet_hdr_len = vnet_hdr_len;
+
+ return 0;
}
static struct net_backend tap_backend = {
@@ -324,13 +432,6 @@
* The netmap backend
*/
-/* The virtio-net features supported by netmap. */
-#define NETMAP_FEATURES (VIRTIO_NET_F_CSUM | VIRTIO_NET_F_HOST_TSO4 | \
- VIRTIO_NET_F_HOST_TSO6 | VIRTIO_NET_F_HOST_UFO | \
- VIRTIO_NET_F_GUEST_CSUM | VIRTIO_NET_F_GUEST_TSO4 | \
- VIRTIO_NET_F_GUEST_TSO6 | VIRTIO_NET_F_GUEST_UFO | \
- VIRTIO_NET_F_MRG_RXBUF)
-
struct netmap_priv {
char ifname[IFNAMSIZ];
struct nm_desc *nmd;
@@ -415,8 +516,11 @@
{
struct netmap_priv *priv = (struct netmap_priv *)be->opaque;
- strlcpy(priv->ifname, devname, sizeof(priv->ifname));
- priv->ifname[sizeof(priv->ifname) - 1] = '\0';
+ if (strlcpy(priv->ifname, devname, sizeof(priv->ifname)) >=
+ sizeof(priv->ifname)) {
+ WPRINTF(("netmap interface name too long\n"));
+ return (-1);
+ }
priv->nmd = nm_open(priv->ifname, NULL, NETMAP_NO_TX_POLL, NULL);
if (priv->nmd == NULL) {

File Metadata

Mime Type
text/plain
Expires
Thu, Apr 9, 10:20 PM (15 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31174058
Default Alt Text
D21315.id.diff (4 KB)

Event Timeline