diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2008-07-29 10:58:37 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-07-28 19:58:37 -0400 |
commit | 398f187d74b89d5ab198fcf9b8d86edbefecec4d (patch) | |
tree | 7aee6787f46a8db0099f37e9dfea787499ecbcd1 | |
parent | 9254926f85466979ef5f0e16386c294bf0973a90 (diff) |
lguest: Use GSO/IFF_VNET_HDR extensions on tun/tap
Guest -> Host 1GB TCP:
Before 20.1974 seconds xmit 214510 recv 5 timeout 214491 usec 278
After 8.43625 seconds xmit 95640 recv 198266 timeout 49771 usec 1252
Host -> Guest 1GB TCP:
Before: Seconds 9.98854 xmit 172166 recv 5344 timeout 172157 usec 251
After: Seconds 5.72803 xmit 244322 recv 9919 timeout 244302 usec 156
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r-- | Documentation/lguest/lguest.c | 34 |
1 files changed, 20 insertions, 14 deletions
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c index 0d1b0265d8e2..dc49f50e04ac 100644 --- a/Documentation/lguest/lguest.c +++ b/Documentation/lguest/lguest.c | |||
@@ -929,11 +929,9 @@ static void handle_net_output(int fd, struct virtqueue *vq, bool timeout) | |||
929 | while ((head = get_vq_desc(vq, iov, &out, &in)) != vq->vring.num) { | 929 | while ((head = get_vq_desc(vq, iov, &out, &in)) != vq->vring.num) { |
930 | if (in) | 930 | if (in) |
931 | errx(1, "Input buffers in output queue?"); | 931 | errx(1, "Input buffers in output queue?"); |
932 | /* Check header, but otherwise ignore it (we told the Guest we | 932 | len = writev(vq->dev->fd, iov, out); |
933 | * supported no features, so it shouldn't have anything | 933 | if (len < 0) |
934 | * interesting). */ | 934 | err(1, "Writing network packet to tun"); |
935 | (void)convert(&iov[0], struct virtio_net_hdr); | ||
936 | len = writev(vq->dev->fd, iov+1, out-1); | ||
937 | add_used_and_trigger(fd, vq, head, len); | 935 | add_used_and_trigger(fd, vq, head, len); |
938 | num++; | 936 | num++; |
939 | } | 937 | } |
@@ -958,7 +956,6 @@ static bool handle_tun_input(int fd, struct device *dev) | |||
958 | unsigned int head, in_num, out_num; | 956 | unsigned int head, in_num, out_num; |
959 | int len; | 957 | int len; |
960 | struct iovec iov[dev->vq->vring.num]; | 958 | struct iovec iov[dev->vq->vring.num]; |
961 | struct virtio_net_hdr *hdr; | ||
962 | 959 | ||
963 | /* First we need a network buffer from the Guests's recv virtqueue. */ | 960 | /* First we need a network buffer from the Guests's recv virtqueue. */ |
964 | head = get_vq_desc(dev->vq, iov, &out_num, &in_num); | 961 | head = get_vq_desc(dev->vq, iov, &out_num, &in_num); |
@@ -977,18 +974,13 @@ static bool handle_tun_input(int fd, struct device *dev) | |||
977 | } else if (out_num) | 974 | } else if (out_num) |
978 | errx(1, "Output buffers in network recv queue?"); | 975 | errx(1, "Output buffers in network recv queue?"); |
979 | 976 | ||
980 | /* First element is the header: we set it to 0 (no features). */ | ||
981 | hdr = convert(&iov[0], struct virtio_net_hdr); | ||
982 | hdr->flags = 0; | ||
983 | hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE; | ||
984 | |||
985 | /* Read the packet from the device directly into the Guest's buffer. */ | 977 | /* Read the packet from the device directly into the Guest's buffer. */ |
986 | len = readv(dev->fd, iov+1, in_num-1); | 978 | len = readv(dev->fd, iov, in_num); |
987 | if (len <= 0) | 979 | if (len <= 0) |
988 | err(1, "reading network"); | 980 | err(1, "reading network"); |
989 | 981 | ||
990 | /* Tell the Guest about the new packet. */ | 982 | /* Tell the Guest about the new packet. */ |
991 | add_used_and_trigger(fd, dev->vq, head, sizeof(*hdr) + len); | 983 | add_used_and_trigger(fd, dev->vq, head, len); |
992 | 984 | ||
993 | verbose("tun input packet len %i [%02x %02x] (%s)\n", len, | 985 | verbose("tun input packet len %i [%02x %02x] (%s)\n", len, |
994 | ((u8 *)iov[1].iov_base)[0], ((u8 *)iov[1].iov_base)[1], | 986 | ((u8 *)iov[1].iov_base)[0], ((u8 *)iov[1].iov_base)[1], |
@@ -1490,11 +1482,15 @@ static int get_tun_device(char tapif[IFNAMSIZ]) | |||
1490 | * the truth, I completely blundered my way through this code, but it | 1482 | * the truth, I completely blundered my way through this code, but it |
1491 | * works now! */ | 1483 | * works now! */ |
1492 | netfd = open_or_die("/dev/net/tun", O_RDWR); | 1484 | netfd = open_or_die("/dev/net/tun", O_RDWR); |
1493 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; | 1485 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR; |
1494 | strcpy(ifr.ifr_name, "tap%d"); | 1486 | strcpy(ifr.ifr_name, "tap%d"); |
1495 | if (ioctl(netfd, TUNSETIFF, &ifr) != 0) | 1487 | if (ioctl(netfd, TUNSETIFF, &ifr) != 0) |
1496 | err(1, "configuring /dev/net/tun"); | 1488 | err(1, "configuring /dev/net/tun"); |
1497 | 1489 | ||
1490 | if (ioctl(netfd, TUNSETOFFLOAD, | ||
1491 | TUN_F_CSUM|TUN_F_TSO4|TUN_F_TSO6|TUN_F_TSO_ECN) != 0) | ||
1492 | err(1, "Could not set features for tun device"); | ||
1493 | |||
1498 | /* We don't need checksums calculated for packets coming in this | 1494 | /* We don't need checksums calculated for packets coming in this |
1499 | * device: trust us! */ | 1495 | * device: trust us! */ |
1500 | ioctl(netfd, TUNSETNOCSUM, 1); | 1496 | ioctl(netfd, TUNSETNOCSUM, 1); |
@@ -1561,6 +1557,16 @@ static void setup_tun_net(char *arg) | |||
1561 | /* Tell Guest what MAC address to use. */ | 1557 | /* Tell Guest what MAC address to use. */ |
1562 | add_feature(dev, VIRTIO_NET_F_MAC); | 1558 | add_feature(dev, VIRTIO_NET_F_MAC); |
1563 | add_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY); | 1559 | add_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY); |
1560 | /* Expect Guest to handle everything except UFO */ | ||
1561 | add_feature(dev, VIRTIO_NET_F_CSUM); | ||
1562 | add_feature(dev, VIRTIO_NET_F_GUEST_CSUM); | ||
1563 | add_feature(dev, VIRTIO_NET_F_MAC); | ||
1564 | add_feature(dev, VIRTIO_NET_F_GUEST_TSO4); | ||
1565 | add_feature(dev, VIRTIO_NET_F_GUEST_TSO6); | ||
1566 | add_feature(dev, VIRTIO_NET_F_GUEST_ECN); | ||
1567 | add_feature(dev, VIRTIO_NET_F_HOST_TSO4); | ||
1568 | add_feature(dev, VIRTIO_NET_F_HOST_TSO6); | ||
1569 | add_feature(dev, VIRTIO_NET_F_HOST_ECN); | ||
1564 | set_config(dev, sizeof(conf), &conf); | 1570 | set_config(dev, sizeof(conf), &conf); |
1565 | 1571 | ||
1566 | /* We don't need the socket any more; setup is done. */ | 1572 | /* We don't need the socket any more; setup is done. */ |