From 6403eab143205a45a5493166ff8bf7e3646f4a77 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 3 Jun 2011 11:51:20 +0000 Subject: drivers/net: Remove unnecessary semicolons Semicolons are not necessary after switch/while/for/if braces so remove them. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/tun.c') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 74e94054ab1..8a27cbf19dd 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -666,7 +666,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, case TUN_TAP_DEV: skb->protocol = eth_type_trans(skb, tun->dev); break; - }; + } if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) { pr_debug("GSO!\n"); -- cgit v1.2.3-70-g09d2 From a504b86e718a425ea4a34e2f95b5cf0545ddfd8d Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 8 Jun 2011 14:33:07 +0000 Subject: tun: reserves space for network in skb The tun driver allocates skb's to hold data from user and then passes the data into the network stack as received data. Most network devices allocate the receive skb with routines like dev_alloc_skb() that reserves additional space for use by network protocol stack but tun does not. Because of the lack of padding, when the packet is passed through bridge netfilter a new skb has to be allocated. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/tun.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/tun.c') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 8a27cbf19dd..17db1942063 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -584,7 +584,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, { struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; struct sk_buff *skb; - size_t len = count, align = 0; + size_t len = count, align = NET_SKB_PAD; struct virtio_net_hdr gso = { 0 }; int offset = 0; @@ -614,7 +614,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, } if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { - align = NET_IP_ALIGN; + align += NET_IP_ALIGN; if (unlikely(len < ETH_HLEN || (gso.hdr_len && gso.hdr_len < ETH_HLEN))) return -EINVAL; -- cgit v1.2.3-70-g09d2 From 6f7c156c08d5eaa9fff2bd062f0a2b9d09a1e7a9 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 8 Jun 2011 14:33:08 +0000 Subject: tun: dont force inline of functions Current standard practice is to not mark most functions as inline and let compiler decide instead. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/tun.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/net/tun.c') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 17db1942063..2829badbae3 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -550,9 +550,9 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) /* prepad is the amount to reserve at front. len is length after that. * linear is a hint as to how much to copy (usually headers). */ -static inline struct sk_buff *tun_alloc_skb(struct tun_struct *tun, - size_t prepad, size_t len, - size_t linear, int noblock) +static struct sk_buff *tun_alloc_skb(struct tun_struct *tun, + size_t prepad, size_t len, + size_t linear, int noblock) { struct sock *sk = tun->socket.sk; struct sk_buff *skb; @@ -578,9 +578,9 @@ static inline struct sk_buff *tun_alloc_skb(struct tun_struct *tun, } /* Get packet from user space buffer */ -static __inline__ ssize_t tun_get_user(struct tun_struct *tun, - const struct iovec *iv, size_t count, - int noblock) +static ssize_t tun_get_user(struct tun_struct *tun, + const struct iovec *iv, size_t count, + int noblock) { struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; struct sk_buff *skb; @@ -729,9 +729,9 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, } /* Put packet to the user space buffer */ -static __inline__ ssize_t tun_put_user(struct tun_struct *tun, - struct sk_buff *skb, - const struct iovec *iv, int len) +static ssize_t tun_put_user(struct tun_struct *tun, + struct sk_buff *skb, + const struct iovec *iv, int len) { struct tun_pi pi = { 0, skb->protocol }; ssize_t total = 0; -- cgit v1.2.3-70-g09d2 From 61a5ff15ebdab87887861a6b128b108404e4706d Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Thu, 9 Jun 2011 00:27:10 -0700 Subject: tun: do not put self in waitq if doing a nonblock read Perf shows a relatively high rate (about 8%) race in spin_lock_irqsave() when doing netperf between external host and guest. It's mainly becuase the lock contention between the tun_do_read() and tun_xmit_skb(), so this patch do not put self into waitqueue to reduce this kind of race. After this patch, it drops to 4%. Signed-off-by: Jason Wang Signed-off-by: Amos Kong Signed-off-by: David S. Miller --- drivers/net/tun.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net/tun.c') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 2829badbae3..ef68e13c042 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -817,7 +817,8 @@ static ssize_t tun_do_read(struct tun_struct *tun, tun_debug(KERN_INFO, tun, "tun_chr_read\n"); - add_wait_queue(&tun->wq.wait, &wait); + if (unlikely(!noblock)) + add_wait_queue(&tun->wq.wait, &wait); while (len) { current->state = TASK_INTERRUPTIBLE; @@ -848,7 +849,8 @@ static ssize_t tun_do_read(struct tun_struct *tun, } current->state = TASK_RUNNING; - remove_wait_queue(&tun->wq.wait, &wait); + if (unlikely(!noblock)) + remove_wait_queue(&tun->wq.wait, &wait); return ret; } -- cgit v1.2.3-70-g09d2 From 10a8d94a95742bb15b4e617ee9884bb4381362be Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Fri, 10 Jun 2011 00:56:17 +0000 Subject: virtio_net: introduce VIRTIO_NET_HDR_F_DATA_VALID There's no need for the guest to validate the checksum if it have been validated by host nics. So this patch introduces a new flag - VIRTIO_NET_HDR_F_DATA_VALID which is used to bypass the checksum examing in guest. The backend (tap/macvtap) may set this flag when met skbs with CHECKSUM_UNNECESSARY to save cpu utilization. No feature negotiation is needed as old driver just ignore this flag. Iperf shows 12%-30% performance improvement for UDP traffic. For TCP, when gro is on no difference as it produces skb with partial checksum. But when gro is disabled, 20% or even higher improvement could be measured by netperf. Signed-off-by: Jason Wang Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 2 ++ drivers/net/tun.c | 2 ++ drivers/net/virtio_net.c | 2 ++ include/linux/virtio_net.h | 1 + net/packet/af_packet.c | 2 ++ 5 files changed, 9 insertions(+) (limited to 'drivers/net/tun.c') diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 6696e56e632..ecee0fe65a9 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -508,6 +508,8 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb, vnet_hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; vnet_hdr->csum_start = skb_checksum_start_offset(skb); vnet_hdr->csum_offset = skb->csum_offset; + } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + vnet_hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID; } /* else everything is zero */ return 0; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index ef68e13c042..4dab85eecb6 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -788,6 +788,8 @@ static ssize_t tun_put_user(struct tun_struct *tun, gso.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; gso.csum_start = skb_checksum_start_offset(skb); gso.csum_offset = skb->csum_offset; + } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + gso.flags = VIRTIO_NET_HDR_F_DATA_VALID; } /* else everything is zero */ if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total, diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index f6853247a62..be3686a298d 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -274,6 +274,8 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len) hdr->hdr.csum_start, hdr->hdr.csum_offset)) goto frame_err; + } else if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) { + skb->ip_summed = CHECKSUM_UNNECESSARY; } skb->protocol = eth_type_trans(skb, dev); diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index 136040bba3e..970d5a2a904 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -63,6 +63,7 @@ struct virtio_net_config { * specify GSO or CSUM features, you can simply ignore the header. */ struct virtio_net_hdr { #define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 // Use csum_start, csum_offset +#define VIRTIO_NET_HDR_F_DATA_VALID 2 // Csum is valid __u8 flags; #define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame #define VIRTIO_NET_HDR_GSO_TCPV4 1 // GSO frame, IPv4 TCP (TSO) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 67f6749a0a4..b54ec41adea 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1685,6 +1685,8 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, vnet_hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; vnet_hdr.csum_start = skb_checksum_start_offset(skb); vnet_hdr.csum_offset = skb->csum_offset; + } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + vnet_hdr.flags = VIRTIO_NET_HDR_F_DATA_VALID; } /* else everything is zero */ err = memcpy_toiovec(msg->msg_iov, (void *)&vnet_hdr, -- cgit v1.2.3-70-g09d2