From ef4252b149cf238480c45c06dcbd567d41ee7d76 Mon Sep 17 00:00:00 2001 From: Michael S. Tsirkin Date: Tue, 13 Jul 2010 17:55:31 +0300 Subject: tap: generalize code for different vnet header len Make host vnet header length a structure field in preparation for using this support in linux kernel. Signed-off-by: Michael S. Tsirkin --- net/tap.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'net/tap.c') diff --git a/net/tap.c b/net/tap.c index 0147dabc15..2866ff40e8 100644 --- a/net/tap.c +++ b/net/tap.c @@ -57,10 +57,10 @@ typedef struct TAPState { uint8_t buf[TAP_BUFSIZE]; unsigned int read_poll : 1; unsigned int write_poll : 1; - unsigned int has_vnet_hdr : 1; unsigned int using_vnet_hdr : 1; unsigned int has_ufo: 1; VHostNetState *vhost_net; + unsigned host_vnet_hdr_len; } TAPState; static int launch_script(const char *setup_script, const char *ifname, int fd); @@ -121,11 +121,11 @@ static ssize_t tap_receive_iov(VLANClientState *nc, const struct iovec *iov, TAPState *s = DO_UPCAST(TAPState, nc, nc); const struct iovec *iovp = iov; struct iovec iov_copy[iovcnt + 1]; - struct virtio_net_hdr hdr = { 0, }; + struct virtio_net_hdr_mrg_rxbuf hdr = { }; - if (s->has_vnet_hdr && !s->using_vnet_hdr) { + if (s->host_vnet_hdr_len && !s->using_vnet_hdr) { iov_copy[0].iov_base = &hdr; - iov_copy[0].iov_len = sizeof(hdr); + iov_copy[0].iov_len = s->host_vnet_hdr_len; memcpy(&iov_copy[1], iov, iovcnt * sizeof(*iov)); iovp = iov_copy; iovcnt++; @@ -139,11 +139,11 @@ static ssize_t tap_receive_raw(VLANClientState *nc, const uint8_t *buf, size_t s TAPState *s = DO_UPCAST(TAPState, nc, nc); struct iovec iov[2]; int iovcnt = 0; - struct virtio_net_hdr hdr = { 0, }; + struct virtio_net_hdr_mrg_rxbuf hdr = { }; - if (s->has_vnet_hdr) { + if (s->host_vnet_hdr_len) { iov[iovcnt].iov_base = &hdr; - iov[iovcnt].iov_len = sizeof(hdr); + iov[iovcnt].iov_len = s->host_vnet_hdr_len; iovcnt++; } @@ -159,7 +159,7 @@ static ssize_t tap_receive(VLANClientState *nc, const uint8_t *buf, size_t size) TAPState *s = DO_UPCAST(TAPState, nc, nc); struct iovec iov[1]; - if (s->has_vnet_hdr && !s->using_vnet_hdr) { + if (s->host_vnet_hdr_len && !s->using_vnet_hdr) { return tap_receive_raw(nc, buf, size); } @@ -202,9 +202,9 @@ static void tap_send(void *opaque) break; } - if (s->has_vnet_hdr && !s->using_vnet_hdr) { - buf += sizeof(struct virtio_net_hdr); - size -= sizeof(struct virtio_net_hdr); + if (s->host_vnet_hdr_len && !s->using_vnet_hdr) { + buf += s->host_vnet_hdr_len; + size -= s->host_vnet_hdr_len; } size = qemu_send_packet_async(&s->nc, buf, size, tap_send_completed); @@ -229,7 +229,7 @@ int tap_has_vnet_hdr(VLANClientState *nc) assert(nc->info->type == NET_CLIENT_TYPE_TAP); - return s->has_vnet_hdr; + return !!s->host_vnet_hdr_len; } void tap_using_vnet_hdr(VLANClientState *nc, int using_vnet_hdr) @@ -239,7 +239,7 @@ void tap_using_vnet_hdr(VLANClientState *nc, int using_vnet_hdr) using_vnet_hdr = using_vnet_hdr != 0; assert(nc->info->type == NET_CLIENT_TYPE_TAP); - assert(s->has_vnet_hdr == using_vnet_hdr); + assert(!!s->host_vnet_hdr_len == using_vnet_hdr); s->using_vnet_hdr = using_vnet_hdr; } @@ -310,7 +310,7 @@ static TAPState *net_tap_fd_init(VLANState *vlan, s = DO_UPCAST(TAPState, nc, nc); s->fd = fd; - s->has_vnet_hdr = vnet_hdr != 0; + s->host_vnet_hdr_len = vnet_hdr ? sizeof(struct virtio_net_hdr) : 0; s->using_vnet_hdr = 0; s->has_ufo = tap_probe_has_ufo(s->fd); tap_set_offload(&s->nc, 0, 0, 0, 0, 0); -- cgit v1.2.3-55-g7522 From 445d892f43e6a6031cd1aac292df433f821aa830 Mon Sep 17 00:00:00 2001 From: Michael S. Tsirkin Date: Fri, 16 Jul 2010 11:16:06 +0300 Subject: tap: add APIs for vnet header length Add APIs to control host header length. First user will be vhost-net. Signed-off-by: Michael S. Tsirkin --- net/tap-aix.c | 9 +++++++++ net/tap-bsd.c | 9 +++++++++ net/tap-linux.c | 29 +++++++++++++++++++++++++++++ net/tap-linux.h | 2 ++ net/tap-solaris.c | 9 +++++++++ net/tap-win32.c | 9 +++++++++ net/tap.c | 21 +++++++++++++++++++++ net/tap.h | 4 ++++ 8 files changed, 92 insertions(+) (limited to 'net/tap.c') diff --git a/net/tap-aix.c b/net/tap-aix.c index 4bc9f2f6d2..e19aaba110 100644 --- a/net/tap-aix.c +++ b/net/tap-aix.c @@ -46,6 +46,15 @@ int tap_probe_has_ufo(int fd) return 0; } +int tap_probe_vnet_hdr_len(int fd, int len) +{ + return 0; +} + +void tap_fd_set_vnet_hdr_len(int fd, int len) +{ +} + void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo) { diff --git a/net/tap-bsd.c b/net/tap-bsd.c index 3773d5da5e..3513075337 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -116,6 +116,15 @@ int tap_probe_has_ufo(int fd) return 0; } +int tap_probe_vnet_hdr_len(int fd, int len) +{ + return 0; +} + +void tap_fd_set_vnet_hdr_len(int fd, int len) +{ +} + void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo) { diff --git a/net/tap-linux.c b/net/tap-linux.c index c92983cb53..f7aa9041b8 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -129,6 +129,35 @@ int tap_probe_has_ufo(int fd) return 1; } +/* Verify that we can assign given length */ +int tap_probe_vnet_hdr_len(int fd, int len) +{ + int orig; + if (ioctl(fd, TUNGETVNETHDRSZ, &orig) == -1) { + return 0; + } + if (ioctl(fd, TUNSETVNETHDRSZ, &len) == -1) { + return 0; + } + /* Restore original length: we can't handle failure. */ + if (ioctl(fd, TUNSETVNETHDRSZ, &orig) == -1) { + fprintf(stderr, "TUNGETVNETHDRSZ ioctl() failed: %s. Exiting.\n", + strerror(errno)); + assert(0); + return -errno; + } + return 1; +} + +void tap_fd_set_vnet_hdr_len(int fd, int len) +{ + if (ioctl(fd, TUNSETVNETHDRSZ, &len) == -1) { + fprintf(stderr, "TUNSETVNETHDRSZ ioctl() failed: %s. Exiting.\n", + strerror(errno)); + assert(0); + } +} + void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo) { diff --git a/net/tap-linux.h b/net/tap-linux.h index 727fcf5010..659e98122b 100644 --- a/net/tap-linux.h +++ b/net/tap-linux.h @@ -27,6 +27,8 @@ #define TUNSETOFFLOAD _IOW('T', 208, unsigned int) #define TUNGETIFF _IOR('T', 210, unsigned int) #define TUNSETSNDBUF _IOW('T', 212, int) +#define TUNGETVNETHDRSZ _IOR('T', 215, int) +#define TUNSETVNETHDRSZ _IOW('T', 216, int) #endif diff --git a/net/tap-solaris.c b/net/tap-solaris.c index 4ac61d2ad6..c216d28267 100644 --- a/net/tap-solaris.c +++ b/net/tap-solaris.c @@ -212,6 +212,15 @@ int tap_probe_has_ufo(int fd) return 0; } +int tap_probe_vnet_hdr_len(int fd, int len) +{ + return 0; +} + +void tap_fd_set_vnet_hdr_len(int fd, int len) +{ +} + void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo) { diff --git a/net/tap-win32.c b/net/tap-win32.c index 74348daf5a..9fe4fcd5f4 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -728,6 +728,15 @@ int tap_has_vnet_hdr(VLANClientState *vc) return 0; } +int tap_probe_vnet_hdr_len(int fd, int len) +{ + return 0; +} + +void tap_fd_set_vnet_hdr_len(int fd, int len) +{ +} + void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr) { } diff --git a/net/tap.c b/net/tap.c index 2866ff40e8..4afb314fde 100644 --- a/net/tap.c +++ b/net/tap.c @@ -232,6 +232,27 @@ int tap_has_vnet_hdr(VLANClientState *nc) return !!s->host_vnet_hdr_len; } +int tap_has_vnet_hdr_len(VLANClientState *nc, int len) +{ + TAPState *s = DO_UPCAST(TAPState, nc, nc); + + assert(nc->info->type == NET_CLIENT_TYPE_TAP); + + return tap_probe_vnet_hdr_len(s->fd, len); +} + +void tap_set_vnet_hdr_len(VLANClientState *nc, int len) +{ + TAPState *s = DO_UPCAST(TAPState, nc, nc); + + assert(nc->info->type == NET_CLIENT_TYPE_TAP); + assert(len == sizeof(struct virtio_net_hdr_mrg_rxbuf) || + len == sizeof(struct virtio_net_hdr)); + + tap_fd_set_vnet_hdr_len(s->fd, len); + s->host_vnet_hdr_len = len; +} + void tap_using_vnet_hdr(VLANClientState *nc, int using_vnet_hdr) { TAPState *s = DO_UPCAST(TAPState, nc, nc); diff --git a/net/tap.h b/net/tap.h index b8cec8320c..e44bd2bc5f 100644 --- a/net/tap.h +++ b/net/tap.h @@ -40,13 +40,17 @@ ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen); int tap_has_ufo(VLANClientState *vc); int tap_has_vnet_hdr(VLANClientState *vc); +int tap_has_vnet_hdr_len(VLANClientState *vc, int len); void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr); void tap_set_offload(VLANClientState *vc, int csum, int tso4, int tso6, int ecn, int ufo); +void tap_set_vnet_hdr_len(VLANClientState *vc, int len); int tap_set_sndbuf(int fd, QemuOpts *opts); int tap_probe_vnet_hdr(int fd); +int tap_probe_vnet_hdr_len(int fd, int len); int tap_probe_has_ufo(int fd); void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo); +void tap_fd_set_vnet_hdr_len(int fd, int len); int tap_get_fd(VLANClientState *vc); -- cgit v1.2.3-55-g7522