From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-0.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 54746C433F5 for ; Thu, 6 Sep 2018 17:51:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1B16620659 for ; Thu, 6 Sep 2018 17:51:09 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1B16620659 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729614AbeIFW1l (ORCPT ); Thu, 6 Sep 2018 18:27:41 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:56864 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728055AbeIFW1j (ORCPT ); Thu, 6 Sep 2018 18:27:39 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 58DA726346; Thu, 6 Sep 2018 17:51:04 +0000 (UTC) Received: from redhat.com (ovpn-120-232.rdu2.redhat.com [10.10.120.232]) by smtp.corp.redhat.com (Postfix) with SMTP id 0E0ADA30B8; Thu, 6 Sep 2018 17:51:04 +0000 (UTC) Date: Thu, 6 Sep 2018 13:51:03 -0400 From: "Michael S. Tsirkin" To: Jason Wang Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, virtualization@lists.linux-foundation.org Subject: Re: [PATCH net-next 09/11] tuntap: accept an array of XDP buffs through sendmsg() Message-ID: <20180906134834-mutt-send-email-mst@kernel.org> References: <20180906040526.22518-1-jasowang@redhat.com> <20180906040526.22518-10-jasowang@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20180906040526.22518-10-jasowang@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Thu, 06 Sep 2018 17:51:04 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Thu, 06 Sep 2018 17:51:04 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'mst@redhat.com' RCPT:'' Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Sep 06, 2018 at 12:05:24PM +0800, Jason Wang wrote: > This patch implement TUN_MSG_PTR msg_control type. This type allows > the caller to pass an array of XDP buffs to tuntap through ptr field > of the tun_msg_control. If an XDP program is attached, tuntap can run > XDP program directly. If not, tuntap will build skb and do a fast > receiving since part of the work has been done by vhost_net. > > This will avoid lots of indirect calls thus improves the icache > utilization and allows to do XDP batched flushing when doing XDP > redirection. > > Signed-off-by: Jason Wang Is most of the benefit in batched flushing or skipping indirect calls? Because if it's flushing we can gain most of it easily by adding an analog of xmit_more. > --- > drivers/net/tun.c | 103 ++++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 100 insertions(+), 3 deletions(-) > > diff --git a/drivers/net/tun.c b/drivers/net/tun.c > index c839a4bdcbd9..069db2e5dd08 100644 > --- a/drivers/net/tun.c > +++ b/drivers/net/tun.c > @@ -2424,22 +2424,119 @@ static void tun_sock_write_space(struct sock *sk) > kill_fasync(&tfile->fasync, SIGIO, POLL_OUT); > } > > +static int tun_xdp_one(struct tun_struct *tun, > + struct tun_file *tfile, > + struct xdp_buff *xdp, int *flush) > +{ > + struct virtio_net_hdr *gso = xdp->data_hard_start + sizeof(int); > + struct tun_pcpu_stats *stats; > + struct bpf_prog *xdp_prog; > + struct sk_buff *skb = NULL; > + u32 rxhash = 0, act; > + int buflen = *(int *)xdp->data_hard_start; > + int err = 0; > + bool skb_xdp = false; > + > + xdp_prog = rcu_dereference(tun->xdp_prog); > + if (xdp_prog) { > + if (gso->gso_type) { > + skb_xdp = true; > + goto build; > + } > + xdp_set_data_meta_invalid(xdp); > + xdp->rxq = &tfile->xdp_rxq; > + act = tun_do_xdp(tun, tfile, xdp_prog, xdp, &err); > + if (err) > + goto out; > + if (act == XDP_REDIRECT) > + *flush = true; > + if (act != XDP_PASS) > + goto out; > + } > + > +build: > + skb = build_skb(xdp->data_hard_start, buflen); > + if (!skb) { > + err = -ENOMEM; > + goto out; > + } > + > + skb_reserve(skb, xdp->data - xdp->data_hard_start); > + skb_put(skb, xdp->data_end - xdp->data); > + > + if (virtio_net_hdr_to_skb(skb, gso, tun_is_little_endian(tun))) { > + this_cpu_inc(tun->pcpu_stats->rx_frame_errors); > + kfree_skb(skb); > + err = -EINVAL; > + goto out; > + } > + > + skb->protocol = eth_type_trans(skb, tun->dev); > + skb_reset_network_header(skb); > + skb_probe_transport_header(skb, 0); > + > + if (skb_xdp) { > + err = do_xdp_generic(xdp_prog, skb); > + if (err != XDP_PASS) > + goto out; > + } > + > + if (!rcu_dereference(tun->steering_prog)) > + rxhash = __skb_get_hash_symmetric(skb); > + > + netif_receive_skb(skb); > + > + stats = get_cpu_ptr(tun->pcpu_stats); > + u64_stats_update_begin(&stats->syncp); > + stats->rx_packets++; > + stats->rx_bytes += skb->len; > + u64_stats_update_end(&stats->syncp); > + put_cpu_ptr(stats); > + > + if (rxhash) > + tun_flow_update(tun, rxhash, tfile); > + > +out: > + return err; > +} > + > static int tun_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len) > { > - int ret; > + int ret, i; > struct tun_file *tfile = container_of(sock, struct tun_file, socket); > struct tun_struct *tun = tun_get(tfile); > struct tun_msg_ctl *ctl = m->msg_control; > + struct xdp_buff *xdp; > > if (!tun) > return -EBADFD; > > - if (ctl && ctl->type != TUN_MSG_UBUF) > - return -EINVAL; > + if (ctl && ((ctl->type & 0xF) == TUN_MSG_PTR)) { > + int n = ctl->type >> 16; > + int flush = 0; > + > + local_bh_disable(); > + rcu_read_lock(); > + > + for (i = 0; i < n; i++) { > + xdp = &((struct xdp_buff *)ctl->ptr)[i]; > + tun_xdp_one(tun, tfile, xdp, &flush); > + } > + > + if (flush) > + xdp_do_flush_map(); > + > + rcu_read_unlock(); > + local_bh_enable(); > + > + ret = total_len; > + goto out; > + } > > ret = tun_get_user(tun, tfile, ctl ? ctl->ptr : NULL, &m->msg_iter, > m->msg_flags & MSG_DONTWAIT, > m->msg_flags & MSG_MORE); > +out: > tun_put(tun); > return ret; > } > -- > 2.17.1