* Re: [V9fs-developer] [PATCH] p9_check_errors() validate PDU length
From: jiangyiwen @ 2018-07-11 2:27 UTC (permalink / raw)
To: Tomas Bortoli, ericvh, rminnich, lucho, Andrew Morton
Cc: netdev, linux-kernel, syzkaller, v9fs-developer, davem
In-Reply-To: <20180709224323.20597-1-tomasbortoli@gmail.com>
On 2018/7/10 6:43, Tomas Bortoli wrote:
> p9_check_errors() does not validate the size of the PDU read
> in p9_parse_header(). Any size can be passed, provoking out-of-bound reads.
>
> Signed-off-by: Tomas Bortoli <tomasbortoli@gmail.com>
> Reported-by: syzbot+65c6b72f284a39d416b4@syzkaller.appspotmail.com
> ---
> As suggested by Dominique:
> https://lkml.org/lkml/2018/7/9/688
> Such check is not enough as it will prevent to read more than how it has
> been allocated but it won't prevent to read more than how it has been read
> So this patch will require some more changes to prevent bad sizes.
>
> net/9p/client.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/net/9p/client.c b/net/9p/client.c
> index 40f7c47f2f74..5b161b576b8a 100644
> --- a/net/9p/client.c
> +++ b/net/9p/client.c
> @@ -520,10 +520,13 @@ EXPORT_SYMBOL(p9_parse_header);
> static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
> {
> int8_t type;
> + int32_t size;
> int err;
> int ecode;
>
> - err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
> + err = p9_parse_header(req->rc, &size, &type, NULL, 0);
> + if (size > req->rc->capacity)
> + return -EINVAL;
Yes, currently 9p client is lacking of properly check for data from server.
Maybe we should have a bigger patch to solve this problem.
> /*
> * dump the response from server
> * This should be after check errors which poplulate pdu_fcall.
>
^ permalink raw reply
* Re: [PATCH v3 net-next] net/sched: add skbprio scheduler
From: Cong Wang @ 2018-07-11 2:25 UTC (permalink / raw)
To: Marcelo Ricardo Leitner
Cc: Michel Machado, Nishanth Devarajan, Jamal Hadi Salim, Jiri Pirko,
David Miller, Linux Kernel Network Developers, Cody Doucette
In-Reply-To: <20180709214016.GD10923@localhost.localdomain>
On Mon, Jul 9, 2018 at 2:40 PM Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
>
> On Mon, Jul 09, 2018 at 05:03:31PM -0400, Michel Machado wrote:
> > Changing TC_PRIO_MAX from 15 to 63 risks breaking backward compatibility
> > with applications.
>
> If done, it needs to be done carefully, indeed. I don't know if it's
> doable, neither I know how hard is your requirement for 64 different
> priorities.
struct tc_prio_qopt {
int bands; /* Number of bands */
__u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */
};
How would you do it carefully?
Also, it is not only used by prio but also pfifo_fast.
^ permalink raw reply
* Re: [net-next, v6, 6/7] net-sysfs: Add interface for Rx queue(s) map per Tx queue
From: Nambiar, Amritha @ 2018-07-11 2:28 UTC (permalink / raw)
To: Andrei Vagin
Cc: netdev, davem, alexander.h.duyck, willemdebruijn.kernel,
sridhar.samudrala, alexander.duyck, edumazet, hannes, tom, tom,
jasowang, gaowanlong
In-Reply-To: <20180704072048.GA29107@outlook.office365.com>
On 7/4/2018 12:20 AM, Andrei Vagin wrote:
> Hello Amritha,
>
> I see a following warning on 4.18.0-rc3-next-20180703.
> It looks like a problem is in this series.
>
> [ 1.084722] ============================================
> [ 1.084797] WARNING: possible recursive locking detected
> [ 1.084872] 4.18.0-rc3-next-20180703+ #1 Not tainted
> [ 1.084949] --------------------------------------------
> [ 1.085024] swapper/0/1 is trying to acquire lock:
> [ 1.085100] 00000000cf973d46 (cpu_hotplug_lock.rw_sem){++++}, at: static_key_slow_inc+0xe/0x20
> [ 1.085189]
> [ 1.085189] but task is already holding lock:
> [ 1.085271] 00000000cf973d46 (cpu_hotplug_lock.rw_sem){++++}, at: init_vqs+0x513/0x5a0
> [ 1.085357]
> [ 1.085357] other info that might help us debug this:
> [ 1.085450] Possible unsafe locking scenario:
> [ 1.085450]
> [ 1.085531] CPU0
> [ 1.085605] ----
> [ 1.085679] lock(cpu_hotplug_lock.rw_sem);
> [ 1.085753] lock(cpu_hotplug_lock.rw_sem);
> [ 1.085828]
> [ 1.085828] *** DEADLOCK ***
> [ 1.085828]
> [ 1.085916] May be due to missing lock nesting notation
> [ 1.085916]
> [ 1.085998] 3 locks held by swapper/0/1:
> [ 1.086074] #0: 00000000244bc7da (&dev->mutex){....}, at: __driver_attach+0x5a/0x110
> [ 1.086164] #1: 00000000cf973d46 (cpu_hotplug_lock.rw_sem){++++}, at: init_vqs+0x513/0x5a0
> [ 1.086248] #2: 000000005cd8463f (xps_map_mutex){+.+.}, at: __netif_set_xps_queue+0x8d/0xc60
> [ 1.086336]
> [ 1.086336] stack backtrace:
> [ 1.086419] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.18.0-rc3-next-20180703+ #1
> [ 1.086504] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
> [ 1.086587] Call Trace:
> [ 1.086667] dump_stack+0x85/0xcb
> [ 1.086744] __lock_acquire+0x68a/0x1330
> [ 1.086821] ? lock_acquire+0x9f/0x200
> [ 1.086900] ? find_held_lock+0x2d/0x90
> [ 1.086976] ? lock_acquire+0x9f/0x200
> [ 1.087051] lock_acquire+0x9f/0x200
> [ 1.087126] ? static_key_slow_inc+0xe/0x20
> [ 1.087205] cpus_read_lock+0x3e/0x80
> [ 1.087280] ? static_key_slow_inc+0xe/0x20
> [ 1.087355] static_key_slow_inc+0xe/0x20
> [ 1.087435] __netif_set_xps_queue+0x216/0xc60
> [ 1.087512] virtnet_set_affinity+0xf0/0x130
> [ 1.087589] init_vqs+0x51b/0x5a0
> [ 1.087665] virtnet_probe+0x39f/0x870
> [ 1.087742] virtio_dev_probe+0x170/0x220
> [ 1.087819] driver_probe_device+0x30b/0x480
> [ 1.087897] ? set_debug_rodata+0x11/0x11
> [ 1.087972] __driver_attach+0xe0/0x110
> [ 1.088064] ? driver_probe_device+0x480/0x480
> [ 1.088141] bus_for_each_dev+0x79/0xc0
> [ 1.088221] bus_add_driver+0x164/0x260
> [ 1.088302] ? veth_init+0x11/0x11
> [ 1.088379] driver_register+0x5b/0xe0
> [ 1.088402] ? veth_init+0x11/0x11
> [ 1.088402] virtio_net_driver_init+0x6d/0x90
> [ 1.088402] do_one_initcall+0x5d/0x34c
> [ 1.088402] ? set_debug_rodata+0x11/0x11
> [ 1.088402] ? rcu_read_lock_sched_held+0x6b/0x80
> [ 1.088402] kernel_init_freeable+0x1ea/0x27b
> [ 1.088402] ? rest_init+0xd0/0xd0
> [ 1.088402] kernel_init+0xa/0x110
> [ 1.088402] ret_from_fork+0x3a/0x50
> [ 1.094190] i8042: PNP: PS/2 Controller [PNP0303:KBD,PNP0f13:MOU] at 0x60,0x64 irq 1,12
>
>
> https://travis-ci.org/avagin/linux/jobs/399867744
>
With this patch series, I introduced static_key for XPS maps
(xps_needed), so static_key_slow_inc() is used to switch branches. The
definition of static_key_slow_inc() has cpus_read_lock in place. In the
virtio_net driver, XPS queues are initialized after setting the
queue:cpu affinity in virtnet_set_affinity() which is already protected
within cpus_read_lock. Hence, the warning here trying to acquire
cpus_read_lock when it is already held.
A quick fix for this would be to just extract netif_set_xps_queue() out
of the lock by simply wrapping it with another put/get_online_cpus
(unlock right before and hold lock right after). But this may not a
clean solution. It'd help if I can get suggestions on what would be a
clean option to fix this without extensively changing the code in
virtio_net. Is it mandatory to protect the affinitization with
read_lock? I don't see similar lock in other drivers while setting the
affinity. I understand this warning should go away, but isn't it safe to
have multiple readers.
> On Fri, Jun 29, 2018 at 09:27:07PM -0700, Amritha Nambiar wrote:
>> Extend transmit queue sysfs attribute to configure Rx queue(s) map
>> per Tx queue. By default no receive queues are configured for the
>> Tx queue.
>>
>> - /sys/class/net/eth0/queues/tx-*/xps_rxqs
>>
>> Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
>> ---
>> net/core/net-sysfs.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 83 insertions(+)
>>
>> diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
>> index b39987c..f25ac5f 100644
>> --- a/net/core/net-sysfs.c
>> +++ b/net/core/net-sysfs.c
>> @@ -1283,6 +1283,88 @@ static ssize_t xps_cpus_store(struct netdev_queue *queue,
>>
>> static struct netdev_queue_attribute xps_cpus_attribute __ro_after_init
>> = __ATTR_RW(xps_cpus);
>> +
>> +static ssize_t xps_rxqs_show(struct netdev_queue *queue, char *buf)
>> +{
>> + struct net_device *dev = queue->dev;
>> + struct xps_dev_maps *dev_maps;
>> + unsigned long *mask, index;
>> + int j, len, num_tc = 1, tc = 0;
>> +
>> + index = get_netdev_queue_index(queue);
>> +
>> + if (dev->num_tc) {
>> + num_tc = dev->num_tc;
>> + tc = netdev_txq_to_tc(dev, index);
>> + if (tc < 0)
>> + return -EINVAL;
>> + }
>> + mask = kcalloc(BITS_TO_LONGS(dev->num_rx_queues), sizeof(long),
>> + GFP_KERNEL);
>> + if (!mask)
>> + return -ENOMEM;
>> +
>> + rcu_read_lock();
>> + dev_maps = rcu_dereference(dev->xps_rxqs_map);
>> + if (!dev_maps)
>> + goto out_no_maps;
>> +
>> + for (j = -1; j = netif_attrmask_next(j, NULL, dev->num_rx_queues),
>> + j < dev->num_rx_queues;) {
>> + int i, tci = j * num_tc + tc;
>> + struct xps_map *map;
>> +
>> + map = rcu_dereference(dev_maps->attr_map[tci]);
>> + if (!map)
>> + continue;
>> +
>> + for (i = map->len; i--;) {
>> + if (map->queues[i] == index) {
>> + set_bit(j, mask);
>> + break;
>> + }
>> + }
>> + }
>> +out_no_maps:
>> + rcu_read_unlock();
>> +
>> + len = bitmap_print_to_pagebuf(false, buf, mask, dev->num_rx_queues);
>> + kfree(mask);
>> +
>> + return len < PAGE_SIZE ? len : -EINVAL;
>> +}
>> +
>> +static ssize_t xps_rxqs_store(struct netdev_queue *queue, const char *buf,
>> + size_t len)
>> +{
>> + struct net_device *dev = queue->dev;
>> + struct net *net = dev_net(dev);
>> + unsigned long *mask, index;
>> + int err;
>> +
>> + if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
>> + return -EPERM;
>> +
>> + mask = kcalloc(BITS_TO_LONGS(dev->num_rx_queues), sizeof(long),
>> + GFP_KERNEL);
>> + if (!mask)
>> + return -ENOMEM;
>> +
>> + index = get_netdev_queue_index(queue);
>> +
>> + err = bitmap_parse(buf, len, mask, dev->num_rx_queues);
>> + if (err) {
>> + kfree(mask);
>> + return err;
>> + }
>> +
>> + err = __netif_set_xps_queue(dev, mask, index, true);
>> + kfree(mask);
>> + return err ? : len;
>> +}
>> +
>> +static struct netdev_queue_attribute xps_rxqs_attribute __ro_after_init
>> + = __ATTR_RW(xps_rxqs);
>> #endif /* CONFIG_XPS */
>>
>> static struct attribute *netdev_queue_default_attrs[] __ro_after_init = {
>> @@ -1290,6 +1372,7 @@ static struct attribute *netdev_queue_default_attrs[] __ro_after_init = {
>> &queue_traffic_class.attr,
>> #ifdef CONFIG_XPS
>> &xps_cpus_attribute.attr,
>> + &xps_rxqs_attribute.attr,
>> &queue_tx_maxrate.attr,
>> #endif
>> NULL
^ permalink raw reply
* Re: [net-next,v3] tcp: Improve setsockopt() TCP_USER_TIMEOUT accuracy
From: Jonathan Maxwell @ 2018-07-11 2:34 UTC (permalink / raw)
To: Eric Dumazet
Cc: David Miller, Eric Dumazet, Neal Cardwell, David Laight, kuznet,
yoshfuji, Netdev, LKML, Jon Maxwell
In-Reply-To: <46861e12-1ae5-374f-e907-87ba6241de5f@gmail.com>
On Wed, Jul 11, 2018 at 12:04 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>
>
> On 07/10/2018 05:33 PM, Jonathan Maxwell wrote:
>> On Tue, Jul 10, 2018 at 10:48 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>>>
>>>
>>> On 07/10/2018 05:38 AM, Eric Dumazet wrote:
>>>
>>>> Note that if we always do jiffies_to_msecs(icsk->icsk_user_timeout) in TCP,
>>>> we also could change the convention and store msecs in this field instead of jiffies.
>>>>
>>>> That would eliminate the msecs_to_jiffies() and jiffies_to_msecs() dance.
>>>>
>>>> (That would be done in a patch of its own, of course)
>>>
>>> tcp_keepalive_timer() does use icsk->icsk_user_timeout directly in jiffies unit,
>>> but considering keeapalive timers are rarely used, this point would have to
>>> do the msecs_to_jiffies() conversion.
>>
>> and also if icsk->icsk_user_timeout = 0, then timeout in retransmits_timed_out()
>> is in jiffies and that would need to addressed.
>
> Absolutely, this is what I was suggesting.
>
> Pseudo code for this part, before your changes.
>
> diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
> index 3b3611729928f77934e0298bb248e55c7a7c5def..cae7bbc956ed51e9d381650957f54550cc0967d9 100644
> --- a/net/ipv4/tcp_timer.c
> +++ b/net/ipv4/tcp_timer.c
> @@ -183,8 +183,9 @@ static bool retransmits_timed_out(struct sock *sk,
> else
> timeout = ((2 << linear_backoff_thresh) - 1) * rto_base +
> (boundary - linear_backoff_thresh) * TCP_RTO_MAX;
> + timeout = jiffies_to_msecs(timeout)'
> }
> - return (tcp_time_stamp(tcp_sk(sk)) - start_ts) >= jiffies_to_msecs(timeout);
> + return (tcp_time_stamp(tcp_sk(sk)) - start_ts) >= timeout;
> }
>
> /* A write timeout has occurred. Process the after effects. */
>
>
That makes sense thanks. I'll look into this and get a patch together.
^ permalink raw reply
* Re: [PATCH v3 net-next] net/sched: add skbprio scheduler
From: Cong Wang @ 2018-07-11 2:32 UTC (permalink / raw)
To: Marcelo Ricardo Leitner
Cc: Michel Machado, Nishanth Devarajan, Jamal Hadi Salim, Jiri Pirko,
David Miller, Linux Kernel Network Developers, Cody Doucette
In-Reply-To: <20180709195319.GD8880@localhost.localdomain>
On Mon, Jul 9, 2018 at 12:53 PM Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
>
> On Mon, Jul 09, 2018 at 02:18:33PM -0400, Michel Machado wrote:
> >
> > 2. sch_prio.c does not have a global limit on the number of packets on
> > all its queues, only a limit per queue.
>
> It can be useful to sch_prio.c as well, why not?
> prio_enqueue()
> {
> ...
> + if (count > sch->global_limit)
> + prio_tail_drop(sch); /* to be implemented */
> ret = qdisc_enqueue(skb, qdisc, to_free);
>
Isn't the whole point of sch_prio offloading the queueing to
each class? If you need a limit, there is one for each child
qdisc if you use for example pfifo or bfifo (depending on you
want to limit bytes or packets).
Also, what's your plan for backward compatibility here?
^ permalink raw reply
* Re: [PATCH v3 net-next] net/sched: add skbprio scheduler
From: Cong Wang @ 2018-07-11 2:38 UTC (permalink / raw)
To: Michel Machado
Cc: Marcelo Ricardo Leitner, Nishanth Devarajan, Jamal Hadi Salim,
Jiri Pirko, David Miller, Linux Kernel Network Developers,
Cody Doucette
In-Reply-To: <b9f0e292-a29a-3c70-a215-cd6fc2ffbc6a@digirati.com.br>
On Mon, Jul 9, 2018 at 11:18 AM Michel Machado <michel@digirati.com.br> wrote:
> 3. The queues of sch_prio.c are struct Qdisc, which don't have a
> method to drop at its tail.
This isn't true, you can install a qdisc which drops at tail as its
child qdisc, you can install different qdiscs for different children
too if you really want. The control is on you, sch_prio is simply a
wrapper.
^ permalink raw reply
* Re: [RFC] Add BPF_SYNCHRONIZE bpf(2) command
From: Lorenzo Colitti @ 2018-07-11 2:46 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Chenbo Feng, dancol, mathieu.desnoyers, Joel Fernandes,
Alexei Starovoitov, lkml, Tim Murray, Daniel Borkmann, netdev
In-Reply-To: <20180710235252.mioihpgtu4n3syaq@ast-mbp.dhcp.thefacebook.com>
On Wed, Jul 11, 2018 at 8:52 AM Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> we need to make sure we have detailed description of BPF_SYNC_MAP_ACCESS
> in uapi/bpf.h, since I feel the confusion regarding its usage is starting already.
> This new cmd will only make sense for map-in-map type of maps.
> Expecting that BPF_SYNC_MAP_ACCESS is somehow implies the end of
> the program or doing some other map synchronization is not correct.
> Commit log of this patch got it right:
> """
> For example, userspace can update a map->map entry to point to a new map,
> use BPF_SYNCHRONIZE to wait for any BPF programs using the old map to
> complete, and then drain the old map without fear that BPF programs
> may still be updating it.
> """
+1 for detailed documentation. For example, consider what happens if
we have two map fds, one active and one standby, and a map-in-map with
one element that contains a pointer to the currently-active map fd.
The kernel program might do:
=====
const int current_map_key = 1;
void *current_map = bpf_map_lookup_elem(outer_map, ¤t_map_key);
int stats_key = 42;
uint64_t *stats_value = bpf_map_lookup_elem(current_map, &stats_key);
__sync_fetch_and_add(&stats_value, 1);
=====
If a userspace does:
1. Write new fd to outer_map[1].
2. Call BPF_SYNC_MAP_ACCESS.
3. Start deleting everything in the old map.
How can we guarantee that the __sync_fetch_and_add will not add to the
old map? If it does, we'll lose data. Will the verifier automatically
hold the RCU lock for as long as a pointer to an inner map is valid?
^ permalink raw reply
* Re: [PATCH net-next v2 0/5] virtio: support packed ring
From: Jason Wang @ 2018-07-11 2:52 UTC (permalink / raw)
To: Tiwei Bie, mst, virtualization, linux-kernel, netdev, virtio-dev
Cc: wexu, jfreimann
In-Reply-To: <20180711022711.7090-1-tiwei.bie@intel.com>
On 2018年07月11日 10:27, Tiwei Bie wrote:
> Hello everyone,
>
> This patch set implements packed ring support in virtio driver.
>
> Some functional tests have been done with Jason's
> packed ring implementation in vhost:
>
> https://lkml.org/lkml/2018/7/3/33
>
> Both of ping and netperf worked as expected.
>
> v1 -> v2:
> - Use READ_ONCE() to read event off_wrap and flags together (Jason);
> - Add comments related to ccw (Jason);
>
> RFC (v6) -> v1:
> - Avoid extra virtio_wmb() in virtqueue_enable_cb_delayed_packed()
> when event idx is off (Jason);
> - Fix bufs calculation in virtqueue_enable_cb_delayed_packed() (Jason);
> - Test the state of the desc at used_idx instead of last_used_idx
> in virtqueue_enable_cb_delayed_packed() (Jason);
> - Save wrap counter (as part of queue state) in the return value
> of virtqueue_enable_cb_prepare_packed();
> - Refine the packed ring definitions in uapi;
> - Rebase on the net-next tree;
>
> RFC v5 -> RFC v6:
> - Avoid tracking addr/len/flags when DMA API isn't used (MST/Jason);
> - Define wrap counter as bool (Jason);
> - Use ALIGN() in vring_init_packed() (Jason);
> - Avoid using pointer to track `next` in detach_buf_packed() (Jason);
> - Add comments for barriers (Jason);
> - Don't enable RING_PACKED on ccw for now (noticed by Jason);
> - Refine the memory barrier in virtqueue_poll();
> - Add a missing memory barrier in virtqueue_enable_cb_delayed_packed();
> - Remove the hacks in virtqueue_enable_cb_prepare_packed();
>
> RFC v4 -> RFC v5:
> - Save DMA addr, etc in desc state (Jason);
> - Track used wrap counter;
>
> RFC v3 -> RFC v4:
> - Make ID allocation support out-of-order (Jason);
> - Various fixes for EVENT_IDX support;
>
> RFC v2 -> RFC v3:
> - Split into small patches (Jason);
> - Add helper virtqueue_use_indirect() (Jason);
> - Just set id for the last descriptor of a list (Jason);
> - Calculate the prev in virtqueue_add_packed() (Jason);
> - Fix/improve desc suppression code (Jason/MST);
> - Refine the code layout for XXX_split/packed and wrappers (MST);
> - Fix the comments and API in uapi (MST);
> - Remove the BUG_ON() for indirect (Jason);
> - Some other refinements and bug fixes;
>
> RFC v1 -> RFC v2:
> - Add indirect descriptor support - compile test only;
> - Add event suppression supprt - compile test only;
> - Move vring_packed_init() out of uapi (Jason, MST);
> - Merge two loops into one in virtqueue_add_packed() (Jason);
> - Split vring_unmap_one() for packed ring and split ring (Jason);
> - Avoid using '%' operator (Jason);
> - Rename free_head -> next_avail_idx (Jason);
> - Add comments for virtio_wmb() in virtqueue_add_packed() (Jason);
> - Some other refinements and bug fixes;
>
> Thanks!
>
> Tiwei Bie (5):
> virtio: add packed ring definitions
> virtio_ring: support creating packed ring
> virtio_ring: add packed ring support
> virtio_ring: add event idx support in packed ring
> virtio_ring: enable packed ring
>
> drivers/s390/virtio/virtio_ccw.c | 14 +
> drivers/virtio/virtio_ring.c | 1365 ++++++++++++++++++++++------
> include/linux/virtio_ring.h | 8 +-
> include/uapi/linux/virtio_config.h | 3 +
> include/uapi/linux/virtio_ring.h | 43 +
> 5 files changed, 1157 insertions(+), 276 deletions(-)
>
Acked-by: Jason Wang <jasowang@redhat.com>
Thanks!
^ permalink raw reply
* Re: [PATCH net-next v5 0/4] net: vhost: improve performance when enable busyloop
From: Jason Wang @ 2018-07-11 2:56 UTC (permalink / raw)
To: xiangxia.m.yue; +Cc: mst, makita.toshiaki, virtualization, netdev
In-Reply-To: <1530678698-33427-1-git-send-email-xiangxia.m.yue@gmail.com>
On 2018年07月04日 12:31, xiangxia.m.yue@gmail.com wrote:
> From: Tonghao Zhang <xiangxia.m.yue@gmail.com>
>
> This patches improve the guest receive and transmit performance.
> On the handle_tx side, we poll the sock receive queue at the same time.
> handle_rx do that in the same way.
>
> For more performance report, see patch 4.
>
> v4 -> v5:
> fix some issues
>
> v3 -> v4:
> fix some issues
>
> v2 -> v3:
> This patches are splited from previous big patch:
> http://patchwork.ozlabs.org/patch/934673/
>
> Tonghao Zhang (4):
> vhost: lock the vqs one by one
> net: vhost: replace magic number of lock annotation
> net: vhost: factor out busy polling logic to vhost_net_busy_poll()
> net: vhost: add rx busy polling in tx path
>
> drivers/vhost/net.c | 108 ++++++++++++++++++++++++++++----------------------
> drivers/vhost/vhost.c | 24 ++++-------
> 2 files changed, 67 insertions(+), 65 deletions(-)
>
Hi, any progress on the new version?
I plan to send a new series of packed virtqueue support of vhost. If you
plan to send it soon, I can wait. Otherwise, I will send my series.
Thanks
^ permalink raw reply
* Re: [PATCH v3 net-next] net/sched: add skbprio scheduler
From: Cong Wang @ 2018-07-11 2:57 UTC (permalink / raw)
To: Nishanth Devarajan
Cc: Jamal Hadi Salim, Jiri Pirko, David Miller,
Linux Kernel Network Developers, Cody Doucette, Michel Machado
In-Reply-To: <20180707101351.GA8300@gmail.com>
On Sat, Jul 7, 2018 at 3:14 AM Nishanth Devarajan <ndev2021@gmail.com> wrote:
> diff --git a/Documentation/networking/sch_skbprio.txt b/Documentation/networking/sch_skbprio.txt
> new file mode 100644
> index 0000000..3aa4d3e
> --- /dev/null
> +++ b/Documentation/networking/sch_skbprio.txt
We usually document each qdisc behavior in tc man pages in iproute2.
I don't mind you document it in kernel, but it kinda breaks the tradition.
> +static int skbprio_change(struct Qdisc *sch, struct nlattr *opt,
> + struct netlink_ext_ack *extack)
> +{
> + struct skbprio_sched_data *q = qdisc_priv(sch);
> + struct tc_skbprio_qopt *ctl = nla_data(opt);
> + const unsigned int min_limit = 1;
> +
> + if (ctl->limit == (typeof(ctl->limit))-1)
> + sch->limit = max(qdisc_dev(sch)->tx_queue_len, min_limit);
> + else if (ctl->limit < min_limit)
> + return -EINVAL;
> + else
> + sch->limit = ctl->limit;
The dev->tx_queue_len is fundamentally non-sense since now
almost every real NIC is multi-queue and qdisc has a completely
different sch->limit. This is why I suggested you to simply
avoid it in your code.
There is no standard way to use dev->tx_queue_len in kernel,
so I can't claim your use is correct or not, but it still looks odd,
other qdisc seems just uses as a default, rather than picking
the smaller or bigger value as a cap.
^ permalink raw reply
* Re: [PATCH bpf-next v3 05/13] tools: libbpf: expose the prog type guessing from section name logic
From: Andrey Ignatov @ 2018-07-11 3:01 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: alexei.starovoitov, daniel, oss-drivers, netdev
In-Reply-To: <20180710214307.4834-6-jakub.kicinski@netronome.com>
Jakub Kicinski <jakub.kicinski@netronome.com> [Tue, 2018-07-10 14:43 -0700]:
> libbpf can guess program type based on ELF section names. As libbpf
> becomes more popular its association between section name strings and
> types becomes more of a standard. Allow libbpf users to use the same
> logic for matching strings to types, e.g. when the string originates
> from command line.
>
> Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
> Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
> ---
> v3 (Andrey):
> - use -EINVAL error code;
> - rename helper to libbpf_prog_type_by_name().
> ---
> tools/lib/bpf/libbpf.c | 43 ++++++++++++++++++++++++------------------
> tools/lib/bpf/libbpf.h | 3 +++
> 2 files changed, 28 insertions(+), 18 deletions(-)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 38ed3e92e393..42f31eff5f3f 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -2081,23 +2081,31 @@ static const struct {
> #undef BPF_S_PROG_SEC
> #undef BPF_SA_PROG_SEC
>
> -static int bpf_program__identify_section(struct bpf_program *prog)
> +int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
> + enum bpf_attach_type *expected_attach_type)
> {
> int i;
>
> - if (!prog->section_name)
> - goto err;
> -
> - for (i = 0; i < ARRAY_SIZE(section_names); i++)
> - if (strncmp(prog->section_name, section_names[i].sec,
> - section_names[i].len) == 0)
> - return i;
> + if (!name)
> + return -EINVAL;
>
> -err:
> - pr_warning("failed to guess program type based on section name %s\n",
> - prog->section_name);
> + for (i = 0; i < ARRAY_SIZE(section_names); i++) {
> + if (strncmp(name, section_names[i].sec, section_names[i].len))
> + continue;
> + *prog_type = section_names[i].prog_type;
> + *expected_attach_type = section_names[i].expected_attach_type;
> + return 0;
> + }
> + return -EINVAL;
> +}
>
> - return -1;
> +static int
> +bpf_program__identify_section(struct bpf_program *prog,
> + enum bpf_prog_type *prog_type,
> + enum bpf_attach_type *expected_attach_type)
> +{
> + return libbpf_prog_type_by_name(prog->section_name, prog_type,
> + expected_attach_type);
> }
>
> int bpf_map__fd(struct bpf_map *map)
> @@ -2230,7 +2238,6 @@ int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
> enum bpf_prog_type prog_type;
> struct bpf_object *obj;
> struct bpf_map *map;
> - int section_idx;
> int err;
>
> if (!attr)
> @@ -2252,14 +2259,14 @@ int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
> prog->prog_ifindex = attr->ifindex;
> expected_attach_type = attr->expected_attach_type;
> if (prog_type == BPF_PROG_TYPE_UNSPEC) {
> - section_idx = bpf_program__identify_section(prog);
> - if (section_idx < 0) {
> + err = bpf_program__identify_section(prog, &prog_type,
> + &expected_attach_type);
> + if (err < 0) {
> + pr_warning("failed to guess program type based on section name %s\n",
> + prog->section_name);
> bpf_object__close(obj);
> return -EINVAL;
> }
> - prog_type = section_names[section_idx].prog_type;
> - expected_attach_type =
> - section_names[section_idx].expected_attach_type;
> }
>
> bpf_program__set_type(prog, prog_type);
> diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
> index 564f4be9bae0..d1ce5c828e2e 100644
> --- a/tools/lib/bpf/libbpf.h
> +++ b/tools/lib/bpf/libbpf.h
> @@ -92,6 +92,9 @@ int bpf_object__set_priv(struct bpf_object *obj, void *priv,
> bpf_object_clear_priv_t clear_priv);
> void *bpf_object__priv(struct bpf_object *prog);
>
> +int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
> + enum bpf_attach_type *expected_attach_type);
> +
> /* Accessors of bpf_program */
> struct bpf_program;
> struct bpf_program *bpf_program__next(struct bpf_program *prog,
> --
> 2.17.1
>
Thanks for changes Jakub!
Acked-by: Andrey Ignatov <rdna@fb.com>
--
Andrey Ignatov
^ permalink raw reply
* Re: [PATCH bpf-next v3 08/13] tools: libbpf: add extended attributes version of bpf_object__open()
From: Andrey Ignatov @ 2018-07-11 3:03 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: alexei.starovoitov, daniel, oss-drivers, netdev
In-Reply-To: <20180710214307.4834-9-jakub.kicinski@netronome.com>
Jakub Kicinski <jakub.kicinski@netronome.com> [Tue, 2018-07-10 14:43 -0700]:
> Similarly to bpf_prog_load() users of bpf_object__open() may need
> to specify the expected program type. Program type is needed at
> open to avoid the kernel version check for program types which don't
> require it.
>
> Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
> Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
> ---
> v3 (Andrey):
> - put file path into the attr struct.
> ---
> tools/lib/bpf/libbpf.c | 26 ++++++++++++++++++++------
> tools/lib/bpf/libbpf.h | 6 ++++++
> 2 files changed, 26 insertions(+), 6 deletions(-)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 30992305f4c1..06cd534d2fba 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -1520,15 +1520,26 @@ __bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz,
> return ERR_PTR(err);
> }
>
> -struct bpf_object *bpf_object__open(const char *path)
> +struct bpf_object *bpf_object__open_xattr(struct bpf_object_open_attr *attr)
> {
> /* param validation */
> - if (!path)
> + if (!attr->file)
> return NULL;
>
> - pr_debug("loading %s\n", path);
> + pr_debug("loading %s\n", attr->file);
> +
> + return __bpf_object__open(attr->file, NULL, 0,
> + bpf_prog_type__needs_kver(attr->prog_type));
> +}
> +
> +struct bpf_object *bpf_object__open(const char *path)
> +{
> + struct bpf_object_open_attr attr = {
> + .file = path,
> + .prog_type = BPF_PROG_TYPE_UNSPEC,
> + };
>
> - return __bpf_object__open(path, NULL, 0, true);
> + return bpf_object__open_xattr(&attr);
> }
>
> struct bpf_object *bpf_object__open_buffer(void *obj_buf,
> @@ -2238,6 +2249,10 @@ int bpf_prog_load(const char *file, enum bpf_prog_type type,
> int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
> struct bpf_object **pobj, int *prog_fd)
> {
> + struct bpf_object_open_attr open_attr = {
> + .file = attr->file,
> + .prog_type = attr->prog_type,
> + };
> struct bpf_program *prog, *first_prog = NULL;
> enum bpf_attach_type expected_attach_type;
> enum bpf_prog_type prog_type;
> @@ -2250,8 +2265,7 @@ int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
> if (!attr->file)
> return -EINVAL;
>
> - obj = __bpf_object__open(attr->file, NULL, 0,
> - bpf_prog_type__needs_kver(attr->prog_type));
> + obj = bpf_object__open_xattr(&open_attr);
> if (IS_ERR_OR_NULL(obj))
> return -ENOENT;
>
> diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
> index 749acf58a5da..e911ad32d02e 100644
> --- a/tools/lib/bpf/libbpf.h
> +++ b/tools/lib/bpf/libbpf.h
> @@ -66,7 +66,13 @@ void libbpf_set_print(libbpf_print_fn_t warn,
> /* Hide internal to user */
> struct bpf_object;
>
> +struct bpf_object_open_attr {
> + const char *file;
> + enum bpf_prog_type prog_type;
> +};
> +
> struct bpf_object *bpf_object__open(const char *path);
> +struct bpf_object *bpf_object__open_xattr(struct bpf_object_open_attr *attr);
> struct bpf_object *bpf_object__open_buffer(void *obj_buf,
> size_t obj_buf_sz,
> const char *name);
> --
> 2.17.1
>
Acked-by: Andrey Ignatov <rdna@fb.com>
--
Andrey Ignatov
^ permalink raw reply
* [PATCH bpf-next v4 0/3] bpf: btf: print bpftool map data with btf
From: Okash Khawaja @ 2018-07-11 3:21 UTC (permalink / raw)
To: Daniel Borkmann, Martin KaFai Lau, Alexei Starovoitov,
Yonghong Song, Quentin Monnet, Jakub Kicinski, David S. Miller
Cc: netdev, kernel-team, linux-kernel
Hi,
Here are the changes from v3:
patch 2:
- use compile time check for big endian
- remove extra parentheses
- don't inline declaration of `data` in loop inside btf_dumper_struct()
- don't print null when char is 0
patch 3:
- return error from get_btf()
- add new line after instantiating struct btf_dumper
Thanks,
Okash
^ permalink raw reply
* [PATCH bpf-next v4 2/3] bpf: btf: add btf print functionality
From: Okash Khawaja @ 2018-07-11 3:21 UTC (permalink / raw)
To: Daniel Borkmann, Martin KaFai Lau, Alexei Starovoitov,
Yonghong Song, Quentin Monnet, Jakub Kicinski, David S. Miller
Cc: netdev, kernel-team, linux-kernel
In-Reply-To: <20180711032108.631367556@fb.com>
[-- Attachment #1: 02-add-btf-dump-map.patch --]
[-- Type: text/plain, Size: 9431 bytes --]
This consumes functionality exported in the previous patch. It does the
main job of printing with BTF data. This is used in the following patch
to provide a more readable output of a map's dump. It relies on
json_writer to do json printing. Below is sample output where map keys
are ints and values are of type struct A:
typedef int int_type;
enum E {
E0,
E1,
};
struct B {
int x;
int y;
};
struct A {
int m;
unsigned long long n;
char o;
int p[8];
int q[4][8];
enum E r;
void *s;
struct B t;
const int u;
int_type v;
unsigned int w1: 3;
unsigned int w2: 3;
};
$ sudo bpftool map dump id 14
[{
"key": 0,
"value": {
"m": 1,
"n": 2,
"o": "c",
"p": [15,16,17,18,15,16,17,18
],
"q": [[25,26,27,28,25,26,27,28
],[35,36,37,38,35,36,37,38
],[45,46,47,48,45,46,47,48
],[55,56,57,58,55,56,57,58
]
],
"r": 1,
"s": 0x7ffd80531cf8,
"t": {
"x": 5,
"y": 10
},
"u": 100,
"v": 20,
"w1": 0x7,
"w2": 0x3
}
}
]
This patch uses json's {} and [] to imply struct/union and array. More
explicit information can be added later. For example, a command line
option can be introduced to print whether a key or value is struct
or union, name of a struct etc. This will however come at the expense
of duplicating info when, for example, printing an array of structs.
enums are printed as ints without their names.
Signed-off-by: Okash Khawaja <osk@fb.com>
---
tools/bpf/bpftool/btf_dumper.c | 248 +++++++++++++++++++++++++++++++++++++++++
tools/bpf/bpftool/main.h | 15 ++
2 files changed, 263 insertions(+)
--- /dev/null
+++ b/tools/bpf/bpftool/btf_dumper.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018 Facebook */
+
+#include <linux/btf.h>
+#include <linux/err.h>
+#include <stdio.h> /* for (FILE *) used by json_writer */
+#include <linux/bitops.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "btf.h"
+#include "json_writer.h"
+#include "main.h"
+
+#define BITS_PER_BYTE_MASK (BITS_PER_BYTE - 1)
+#define BITS_PER_BYTE_MASKED(bits) ((bits) & BITS_PER_BYTE_MASK)
+#define BITS_ROUNDDOWN_BYTES(bits) ((bits) >> 3)
+#define BITS_ROUNDUP_BYTES(bits) \
+ (BITS_ROUNDDOWN_BYTES(bits) + !!BITS_PER_BYTE_MASKED(bits))
+
+static int btf_dumper_do_type(const struct btf_dumper *d, __u32 type_id,
+ __u8 bit_offset, const void *data);
+
+static void btf_dumper_ptr(const void *data, json_writer_t *jw,
+ bool is_plain_text)
+{
+ if (is_plain_text)
+ jsonw_printf(jw, "%p", *((unsigned long *)data));
+ else
+ jsonw_printf(jw, "%u", *((unsigned long *)data));
+}
+
+static int btf_dumper_modifier(const struct btf_dumper *d, __u32 type_id,
+ const void *data)
+{
+ int actual_type_id;
+
+ actual_type_id = btf__resolve_type(d->btf, type_id);
+ if (actual_type_id < 0)
+ return actual_type_id;
+
+ return btf_dumper_do_type(d, actual_type_id, 0, data);
+}
+
+static void btf_dumper_enum(const void *data, json_writer_t *jw)
+{
+ jsonw_printf(jw, "%d", *(int *)data);
+}
+
+static int btf_dumper_array(const struct btf_dumper *d, __u32 type_id,
+ const void *data)
+{
+ const struct btf_type *t = btf__type_by_id(d->btf, type_id);
+ struct btf_array *arr = (struct btf_array *)(t + 1);
+ long long elem_size;
+ int ret = 0;
+ __u32 i;
+
+ elem_size = btf__resolve_size(d->btf, arr->type);
+ if (elem_size < 0)
+ return elem_size;
+
+ jsonw_start_array(d->jw);
+ for (i = 0; i < arr->nelems; i++) {
+ ret = btf_dumper_do_type(d, arr->type, 0,
+ data + i * elem_size);
+ if (ret)
+ break;
+ }
+
+ jsonw_end_array(d->jw);
+ return ret;
+}
+
+static void btf_dumper_int_bits(__u32 int_type, __u8 bit_offset,
+ const void *data, json_writer_t *jw,
+ bool is_plain_text)
+{
+ int left_shift_bits, right_shift_bits;
+ int nr_bits = BTF_INT_BITS(int_type);
+ int total_bits_offset;
+ int bytes_to_copy;
+ int bits_to_copy;
+ __u64 print_num;
+
+ total_bits_offset = bit_offset + BTF_INT_OFFSET(int_type);
+ data += BITS_ROUNDDOWN_BYTES(total_bits_offset);
+ bit_offset = BITS_PER_BYTE_MASKED(total_bits_offset);
+ bits_to_copy = bit_offset + nr_bits;
+ bytes_to_copy = BITS_ROUNDUP_BYTES(bits_to_copy);
+
+ print_num = 0;
+ memcpy(&print_num, data, bytes_to_copy);
+#ifdef __BIG_ENDIAN_BITFIELD
+ left_shift_bits = bit_offset;
+#else
+ left_shift_bits = 64 - bits_to_copy;
+#endif
+ right_shift_bits = 64 - nr_bits;
+
+ print_num <<= left_shift_bits;
+ print_num >>= right_shift_bits;
+ if (is_plain_text)
+ jsonw_printf(jw, "0x%llx", print_num);
+ else
+ jsonw_printf(jw, "%llu", print_num);
+}
+
+static int btf_dumper_int(const struct btf_type *t, __u8 bit_offset,
+ const void *data, json_writer_t *jw,
+ bool is_plain_text)
+{
+ __u32 *int_type;
+ __u32 nr_bits;
+
+ int_type = (__u32 *)(t + 1);
+ nr_bits = BTF_INT_BITS(*int_type);
+ /* if this is bit field */
+ if (bit_offset || BTF_INT_OFFSET(*int_type) ||
+ BITS_PER_BYTE_MASKED(nr_bits)) {
+ btf_dumper_int_bits(*int_type, bit_offset, data, jw,
+ is_plain_text);
+ return 0;
+ }
+
+ switch (BTF_INT_ENCODING(*int_type)) {
+ case 0:
+ if (BTF_INT_BITS(*int_type) == 64)
+ jsonw_printf(jw, "%lu", *(__u64 *)data);
+ else if (BTF_INT_BITS(*int_type) == 32)
+ jsonw_printf(jw, "%u", *(__u32 *)data);
+ else if (BTF_INT_BITS(*int_type) == 16)
+ jsonw_printf(jw, "%hu", *(__u16 *)data);
+ else if (BTF_INT_BITS(*int_type) == 8)
+ jsonw_printf(jw, "%hhu", *(__u8 *)data);
+ else
+ btf_dumper_int_bits(*int_type, bit_offset, data, jw,
+ is_plain_text);
+ break;
+ case BTF_INT_SIGNED:
+ if (BTF_INT_BITS(*int_type) == 64)
+ jsonw_printf(jw, "%ld", *(long long *)data);
+ else if (BTF_INT_BITS(*int_type) == 32)
+ jsonw_printf(jw, "%d", *(int *)data);
+ else if (BTF_INT_BITS(*int_type) == 16)
+ jsonw_printf(jw, "%hd", *(short *)data);
+ else if (BTF_INT_BITS(*int_type) == 8)
+ jsonw_printf(jw, "%hhd", *(char *)data);
+ else
+ btf_dumper_int_bits(*int_type, bit_offset, data, jw,
+ is_plain_text);
+ break;
+ case BTF_INT_CHAR:
+ if (isprint(*(char *)data))
+ jsonw_printf(jw, "\"%c\"", *(char *)data);
+ else
+ if (is_plain_text)
+ jsonw_printf(jw, "0x%hhx", *(char *)data);
+ else
+ jsonw_printf(jw, "\"\\u00%02hhx\"",
+ *(char *)data);
+ break;
+ case BTF_INT_BOOL:
+ jsonw_bool(jw, *(int *)data);
+ break;
+ default:
+ /* shouldn't happen */
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int btf_dumper_struct(const struct btf_dumper *d, __u32 type_id,
+ const void *data)
+{
+ const struct btf_type *t;
+ struct btf_member *m;
+ const void *data_off;
+ int ret = 0;
+ int i, vlen;
+
+ t = btf__type_by_id(d->btf, type_id);
+ if (!t)
+ return -EINVAL;
+
+ vlen = BTF_INFO_VLEN(t->info);
+ jsonw_start_object(d->jw);
+ m = (struct btf_member *)(t + 1);
+
+ for (i = 0; i < vlen; i++) {
+ data_off = data + BITS_ROUNDDOWN_BYTES(m[i].offset);
+ jsonw_name(d->jw, btf__name_by_offset(d->btf, m[i].name_off));
+ ret = btf_dumper_do_type(d, m[i].type,
+ BITS_PER_BYTE_MASKED(m[i].offset),
+ data_off);
+ if (ret)
+ break;
+ }
+
+ jsonw_end_object(d->jw);
+
+ return ret;
+}
+
+static int btf_dumper_do_type(const struct btf_dumper *d, __u32 type_id,
+ __u8 bit_offset, const void *data)
+{
+ const struct btf_type *t = btf__type_by_id(d->btf, type_id);
+
+ switch (BTF_INFO_KIND(t->info)) {
+ case BTF_KIND_INT:
+ return btf_dumper_int(t, bit_offset, data, d->jw,
+ d->is_plain_text);
+ case BTF_KIND_STRUCT:
+ case BTF_KIND_UNION:
+ return btf_dumper_struct(d, type_id, data);
+ case BTF_KIND_ARRAY:
+ return btf_dumper_array(d, type_id, data);
+ case BTF_KIND_ENUM:
+ btf_dumper_enum(data, d->jw);
+ return 0;
+ case BTF_KIND_PTR:
+ btf_dumper_ptr(data, d->jw, d->is_plain_text);
+ return 0;
+ case BTF_KIND_UNKN:
+ jsonw_printf(d->jw, "(unknown)");
+ return 0;
+ case BTF_KIND_FWD:
+ /* map key or value can't be forward */
+ jsonw_printf(d->jw, "(fwd-kind-invalid)");
+ return -EINVAL;
+ case BTF_KIND_TYPEDEF:
+ case BTF_KIND_VOLATILE:
+ case BTF_KIND_CONST:
+ case BTF_KIND_RESTRICT:
+ return btf_dumper_modifier(d, type_id, data);
+ default:
+ jsonw_printf(d->jw, "(unsupported-kind");
+ return -EINVAL;
+ }
+}
+
+int btf_dumper_type(const struct btf_dumper *d, __u32 type_id,
+ const void *data)
+{
+ return btf_dumper_do_type(d, type_id, 0, data);
+}
--- a/tools/bpf/bpftool/main.h
+++ b/tools/bpf/bpftool/main.h
@@ -131,4 +131,19 @@ unsigned int get_page_size(void);
unsigned int get_possible_cpus(void);
const char *ifindex_to_bfd_name_ns(__u32 ifindex, __u64 ns_dev, __u64 ns_ino);
+struct btf_dumper {
+ const struct btf *btf;
+ json_writer_t *jw;
+ bool is_plain_text;
+};
+
+/* btf_dumper_type - print data along with type information
+ * @d: an instance containing context for dumping types
+ * @type_id: index in btf->types array. this points to the type to be dumped
+ * @data: pointer the actual data, i.e. the values to be printed
+ *
+ * Returns zero on success and negative error code otherwise
+ */
+int btf_dumper_type(const struct btf_dumper *d, __u32 type_id,
+ const void *data);
#endif
^ permalink raw reply
* [PATCH bpf-next v4 3/3] bpf: btf: print map dump and lookup with btf info
From: Okash Khawaja @ 2018-07-11 3:21 UTC (permalink / raw)
To: Daniel Borkmann, Martin KaFai Lau, Alexei Starovoitov,
Yonghong Song, Quentin Monnet, Jakub Kicinski, David S. Miller
Cc: netdev, kernel-team, linux-kernel
In-Reply-To: <20180711032108.631367556@fb.com>
[-- Attachment #1: 03-json-print-btf-info-for-map --]
[-- Type: text/plain, Size: 8313 bytes --]
This patch augments the output of bpftool's map dump and map lookup
commands to print data along side btf info, if the correspondin btf
info is available. The outputs for each of map dump and map lookup
commands are augmented in two ways:
1. when neither of -j and -p are supplied, btf-ful map data is printed
whose aim is human readability. This means no commitments for json- or
backward- compatibility.
2. when either -j or -p are supplied, a new json object named
"formatted" is added for each key-value pair. This object contains the
same data as the key-value pair, but with btf info. "formatted" object
promises json- and backward- compatibility. Below is a sample output.
$ bpftool map dump -p id 8
[{
"key": ["0x0f","0x00","0x00","0x00"
],
"value": ["0x03", "0x00", "0x00", "0x00", ...
],
"formatted": {
"key": 15,
"value": {
"int_field": 3,
...
}
}
}
]
This patch calls btf_dumper introduced in previous patch to accomplish
the above. Indeed, btf-ful info is only displayed if btf data for the
given map is available. Otherwise existing output is displayed as-is.
Signed-off-by: Okash Khawaja <osk@fb.com>
---
tools/bpf/bpftool/map.c | 217 ++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 201 insertions(+), 16 deletions(-)
--- a/tools/bpf/bpftool/map.c
+++ b/tools/bpf/bpftool/map.c
@@ -34,6 +34,7 @@
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
+#include <linux/err.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -44,6 +45,8 @@
#include <bpf.h>
+#include "btf.h"
+#include "json_writer.h"
#include "main.h"
static const char * const map_type_name[] = {
@@ -148,8 +151,109 @@ int map_parse_fd_and_info(int *argc, cha
return fd;
}
+static int do_dump_btf(const struct btf_dumper *d,
+ struct bpf_map_info *map_info, void *key,
+ void *value)
+{
+ int ret;
+
+ /* start of key-value pair */
+ jsonw_start_object(d->jw);
+
+ jsonw_name(d->jw, "key");
+
+ ret = btf_dumper_type(d, map_info->btf_key_type_id, key);
+ if (ret)
+ goto err_end_obj;
+
+ jsonw_name(d->jw, "value");
+
+ ret = btf_dumper_type(d, map_info->btf_value_type_id, value);
+
+err_end_obj:
+ /* end of key-value pair */
+ jsonw_end_object(d->jw);
+
+ return ret;
+}
+
+static int get_btf(struct bpf_map_info *map_info, struct btf **btf)
+{
+ struct bpf_btf_info btf_info = { 0 };
+ __u32 len = sizeof(btf_info);
+ __u32 last_size;
+ int btf_fd;
+ void *ptr;
+ int err;
+
+ err = 0;
+ *btf = NULL;
+ btf_fd = bpf_btf_get_fd_by_id(map_info->btf_id);
+ if (btf_fd < 0)
+ return 0;
+
+ /* we won't know btf_size until we call bpf_obj_get_info_by_fd(). so
+ * let's start with a sane default - 4KiB here - and resize it only if
+ * bpf_obj_get_info_by_fd() needs a bigger buffer.
+ */
+ btf_info.btf_size = 4096;
+ last_size = btf_info.btf_size;
+ ptr = malloc(last_size);
+ if (!ptr) {
+ err = -ENOMEM;
+ goto exit_free;
+ }
+
+ bzero(ptr, last_size);
+ btf_info.btf = ptr_to_u64(ptr);
+ err = bpf_obj_get_info_by_fd(btf_fd, &btf_info, &len);
+
+ if (!err && btf_info.btf_size > last_size) {
+ void *temp_ptr;
+
+ last_size = btf_info.btf_size;
+ temp_ptr = realloc(ptr, last_size);
+ if (!temp_ptr) {
+ err = -ENOMEM;
+ goto exit_free;
+ }
+ ptr = temp_ptr;
+ bzero(ptr, last_size);
+ btf_info.btf = ptr_to_u64(ptr);
+ err = bpf_obj_get_info_by_fd(btf_fd, &btf_info, &len);
+ }
+
+ if (err || btf_info.btf_size > last_size) {
+ err = errno;
+ goto exit_free;
+ }
+
+ *btf = btf__new((__u8 *)btf_info.btf, btf_info.btf_size, NULL);
+ if (IS_ERR(*btf)) {
+ err = PTR_ERR(btf);
+ *btf = NULL;
+ }
+
+exit_free:
+ close(btf_fd);
+ free(ptr);
+
+ return err;
+}
+
+static json_writer_t *get_btf_writer(void)
+{
+ json_writer_t *jw = jsonw_new(stdout);
+
+ if (!jw)
+ return NULL;
+ jsonw_pretty(jw, true);
+
+ return jw;
+}
+
static void print_entry_json(struct bpf_map_info *info, unsigned char *key,
- unsigned char *value)
+ unsigned char *value, struct btf *btf)
{
jsonw_start_object(json_wtr);
@@ -158,6 +262,16 @@ static void print_entry_json(struct bpf_
print_hex_data_json(key, info->key_size);
jsonw_name(json_wtr, "value");
print_hex_data_json(value, info->value_size);
+ if (btf) {
+ struct btf_dumper d = {
+ .btf = btf,
+ .jw = json_wtr,
+ .is_plain_text = false,
+ };
+
+ jsonw_name(json_wtr, "formatted");
+ do_dump_btf(&d, info, key, value);
+ }
} else {
unsigned int i, n;
@@ -508,10 +622,12 @@ static int do_show(int argc, char **argv
static int do_dump(int argc, char **argv)
{
+ struct bpf_map_info info = {};
void *key, *value, *prev_key;
unsigned int num_elems = 0;
- struct bpf_map_info info = {};
__u32 len = sizeof(info);
+ json_writer_t *btf_wtr;
+ struct btf *btf = NULL;
int err;
int fd;
@@ -537,8 +653,27 @@ static int do_dump(int argc, char **argv
}
prev_key = NULL;
+
+ err = get_btf(&info, &btf);
+ if (err) {
+ p_err("failed to get btf");
+ goto exit_free;
+ }
+
if (json_output)
jsonw_start_array(json_wtr);
+ else
+ if (btf) {
+ btf_wtr = get_btf_writer();
+ if (!btf_wtr) {
+ p_info("failed to create json writer for btf. falling back to plain output");
+ btf__free(btf);
+ btf = NULL;
+ } else {
+ jsonw_start_array(btf_wtr);
+ }
+ }
+
while (true) {
err = bpf_map_get_next_key(fd, prev_key, key);
if (err) {
@@ -549,9 +684,19 @@ static int do_dump(int argc, char **argv
if (!bpf_map_lookup_elem(fd, key, value)) {
if (json_output)
- print_entry_json(&info, key, value);
+ print_entry_json(&info, key, value, btf);
else
- print_entry_plain(&info, key, value);
+ if (btf) {
+ struct btf_dumper d = {
+ .btf = btf,
+ .jw = btf_wtr,
+ .is_plain_text = true,
+ };
+
+ do_dump_btf(&d, &info, key, value);
+ } else {
+ print_entry_plain(&info, key, value);
+ }
} else {
if (json_output) {
jsonw_name(json_wtr, "key");
@@ -574,14 +719,19 @@ static int do_dump(int argc, char **argv
if (json_output)
jsonw_end_array(json_wtr);
- else
+ else if (btf) {
+ jsonw_end_array(btf_wtr);
+ jsonw_destroy(&btf_wtr);
+ } else {
printf("Found %u element%s\n", num_elems,
num_elems != 1 ? "s" : "");
+ }
exit_free:
free(key);
free(value);
close(fd);
+ btf__free(btf);
return err;
}
@@ -637,6 +787,8 @@ static int do_lookup(int argc, char **ar
{
struct bpf_map_info info = {};
__u32 len = sizeof(info);
+ json_writer_t *btf_wtr;
+ struct btf *btf = NULL;
void *key, *value;
int err;
int fd;
@@ -661,27 +813,60 @@ static int do_lookup(int argc, char **ar
goto exit_free;
err = bpf_map_lookup_elem(fd, key, value);
- if (!err) {
- if (json_output)
- print_entry_json(&info, key, value);
- else
+ if (err) {
+ if (errno == ENOENT) {
+ if (json_output) {
+ jsonw_null(json_wtr);
+ } else {
+ printf("key:\n");
+ fprint_hex(stdout, key, info.key_size, " ");
+ printf("\n\nNot found\n");
+ }
+ } else {
+ p_err("lookup failed: %s", strerror(errno));
+ }
+
+ goto exit_free;
+ }
+
+ /* here means bpf_map_lookup_elem() succeeded */
+ err = get_btf(&info, &btf);
+ if (err) {
+ p_err("failed to get btf");
+ goto exit_free;
+ }
+
+ if (json_output) {
+ print_entry_json(&info, key, value, btf);
+ } else if (btf) {
+ /* if here json_wtr wouldn't have been initialised,
+ * so let's create separate writer for btf
+ */
+ btf_wtr = get_btf_writer();
+ if (!btf_wtr) {
+ p_info("failed to create json writer for btf. falling back to plain output");
+ btf__free(btf);
+ btf = NULL;
print_entry_plain(&info, key, value);
- } else if (errno == ENOENT) {
- if (json_output) {
- jsonw_null(json_wtr);
} else {
- printf("key:\n");
- fprint_hex(stdout, key, info.key_size, " ");
- printf("\n\nNot found\n");
+ struct btf_dumper d = {
+ .btf = btf,
+ .jw = btf_wtr,
+ .is_plain_text = true,
+ };
+
+ do_dump_btf(&d, &info, key, value);
+ jsonw_destroy(&btf_wtr);
}
} else {
- p_err("lookup failed: %s", strerror(errno));
+ print_entry_plain(&info, key, value);
}
exit_free:
free(key);
free(value);
close(fd);
+ btf__free(btf);
return err;
}
^ permalink raw reply
* Re: [RFC] Add BPF_SYNCHRONIZE bpf(2) command
From: Alexei Starovoitov @ 2018-07-11 3:40 UTC (permalink / raw)
To: Lorenzo Colitti
Cc: Chenbo Feng, dancol, mathieu.desnoyers, Joel Fernandes,
Alexei Starovoitov, lkml, Tim Murray, Daniel Borkmann, netdev
In-Reply-To: <CAKD1Yr07uxpd95oGAE7QxfrS_qWuiLcUmy7nsEsC0CzVhV2-rg@mail.gmail.com>
On Wed, Jul 11, 2018 at 11:46:19AM +0900, Lorenzo Colitti wrote:
> On Wed, Jul 11, 2018 at 8:52 AM Alexei Starovoitov
> <alexei.starovoitov@gmail.com> wrote:
> >
> > we need to make sure we have detailed description of BPF_SYNC_MAP_ACCESS
> > in uapi/bpf.h, since I feel the confusion regarding its usage is starting already.
> > This new cmd will only make sense for map-in-map type of maps.
> > Expecting that BPF_SYNC_MAP_ACCESS is somehow implies the end of
> > the program or doing some other map synchronization is not correct.
> > Commit log of this patch got it right:
> > """
> > For example, userspace can update a map->map entry to point to a new map,
> > use BPF_SYNCHRONIZE to wait for any BPF programs using the old map to
> > complete, and then drain the old map without fear that BPF programs
> > may still be updating it.
> > """
>
> +1 for detailed documentation. For example, consider what happens if
> we have two map fds, one active and one standby, and a map-in-map with
> one element that contains a pointer to the currently-active map fd.
yes. that's exactly the use case that folks use.
> The kernel program might do:
>
> =====
> const int current_map_key = 1;
> void *current_map = bpf_map_lookup_elem(outer_map, ¤t_map_key);
>
> int stats_key = 42;
> uint64_t *stats_value = bpf_map_lookup_elem(current_map, &stats_key);
> __sync_fetch_and_add(&stats_value, 1);
> =====
>
> If a userspace does:
>
> 1. Write new fd to outer_map[1].
> 2. Call BPF_SYNC_MAP_ACCESS.
> 3. Start deleting everything in the old map.
>
> How can we guarantee that the __sync_fetch_and_add will not add to the
> old map?
without any changes to the kernel sys_membarrier will work.
And that's what folks use already.
BPF_SYNC_MAP_ACCESS implemented via synchronize_rcu() will work
as well whether in the current implementation where rcu_lock/unlock
is done outside of the program and in the future when
rcu_lock/unlock are called by the program itself.
> Will the verifier automatically
> hold the RCU lock for as long as a pointer to an inner map is valid?
the verifier will guarantee the equivalency of future explicit
lock/unlock by the program vs current situation of implicit
lock/unlock by the kernel.
The verifier will track that bpf_map_lookup_elem() is done
after rcu_lock and that the value returned by this helper is
not accessed after rcu_unlock. Baby steps of dataflow analysis.
^ permalink raw reply
* Re: [PATCH bpf-next v3 12/13] tools: libbpf: allow map reuse
From: Andrey Ignatov @ 2018-07-11 3:45 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: alexei.starovoitov, daniel, oss-drivers, netdev
In-Reply-To: <20180710214307.4834-13-jakub.kicinski@netronome.com>
Jakub Kicinski <jakub.kicinski@netronome.com> [Tue, 2018-07-10 14:43 -0700]:
> More advanced applications may want to only replace programs without
> destroying associated maps. Allow libbpf users to achieve that.
> Instead of always creating all of the maps at load time, expose to
> users an API to reconstruct the map object from already existing
> map.
>
> The map parameters are read from the kernel and replace the parameters
> of the ELF map. libbpf does not restrict the map replacement, i.e.
> the reused map does not have to be compatible with the ELF map
> definition. We relay on the verifier for checking the compatibility
> between maps and programs. The ELF map definition is completely
> overwritten by the information read from the kernel, to make sure
> libbpf's view of map object corresponds to the actual map.
>
> Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
> Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
> ---
> v3 (Andrey):
> - use dup3();
> - close existing fd;
> - handle errors better;
> - depend on fd value to determine pre-set.
> ---
> tools/lib/bpf/libbpf.c | 53 ++++++++++++++++++++++++++++++++++++++++++
> tools/lib/bpf/libbpf.h | 1 +
> 2 files changed, 54 insertions(+)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index fd2c4433863d..955f8eafbf41 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -1035,6 +1035,53 @@ static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf)
> return 0;
> }
>
> +int bpf_map__reuse_fd(struct bpf_map *map, int fd)
> +{
> + struct bpf_map_info info = {};
> + __u32 len = sizeof(info);
> + int new_fd, err;
> + char *new_name;
> +
> + err = bpf_obj_get_info_by_fd(fd, &info, &len);
> + if (err)
> + return err;
> +
> + new_name = strdup(info.name);
> + if (!new_name)
> + return -errno;
> +
> + new_fd = open("/", O_RDONLY | O_CLOEXEC);
> + if (new_fd < 0)
> + goto err_free_new_name;
> +
> + new_fd = dup3(fd, new_fd, O_CLOEXEC);
> + if (new_fd < 0)
> + goto err_close_new_fd;
> +
> + err = zclose(map->fd);
> + if (err)
> + goto err_close_new_fd;
> + free(map->name);
> +
> + map->fd = new_fd;
> + map->name = new_name;
> + map->def.type = info.type;
> + map->def.key_size = info.key_size;
> + map->def.value_size = info.value_size;
> + map->def.max_entries = info.max_entries;
> + map->def.map_flags = info.map_flags;
> + map->btf_key_type_id = info.btf_key_type_id;
> + map->btf_value_type_id = info.btf_value_type_id;
> +
> + return 0;
> +
> +err_close_new_fd:
> + close(new_fd);
> +err_free_new_name:
> + free(new_name);
> + return -errno;
> +}
> +
> static int
> bpf_object__create_maps(struct bpf_object *obj)
> {
> @@ -1047,6 +1094,12 @@ bpf_object__create_maps(struct bpf_object *obj)
> struct bpf_map_def *def = &map->def;
> int *pfd = &map->fd;
>
> + if (map->fd >= 0) {
> + pr_debug("skip map create (preset) %s: fd=%d\n",
> + map->name, map->fd);
> + continue;
> + }
> +
> create_attr.name = map->name;
> create_attr.map_ifindex = map->map_ifindex;
> create_attr.map_type = def->type;
> diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
> index e911ad32d02e..1f8fc2060460 100644
> --- a/tools/lib/bpf/libbpf.h
> +++ b/tools/lib/bpf/libbpf.h
> @@ -261,6 +261,7 @@ typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
> int bpf_map__set_priv(struct bpf_map *map, void *priv,
> bpf_map_clear_priv_t clear_priv);
> void *bpf_map__priv(struct bpf_map *map);
> +int bpf_map__reuse_fd(struct bpf_map *map, int fd);
> bool bpf_map__is_offload_neutral(struct bpf_map *map);
> void bpf_map__set_ifindex(struct bpf_map *map, __u32 ifindex);
> int bpf_map__pin(struct bpf_map *map, const char *path);
> --
> 2.17.1
>
Acked-by: Andrey Ignatov <rdna@fb.com>
Thanks for all the changes Jakub! Sorry, it forced you to deal with
strerror_r().
One thing, I'm not really sure, is if there is a reason not to copy
ifindex as well from the map that corresponds to passed fd. It's fine
with me to follow-up separately though if it's needed.
--
Andrey Ignatov
^ permalink raw reply
* Re: [PATCH net-next v5 0/4] net: vhost: improve performance when enable busyloop
From: Tonghao Zhang @ 2018-07-11 3:49 UTC (permalink / raw)
To: jasowang; +Cc: Linux Kernel Network Developers, virtualization, mst
In-Reply-To: <934375dc-8925-c271-b2b0-b224ff5191c2@redhat.com>
On Wed, Jul 11, 2018 at 10:56 AM Jason Wang <jasowang@redhat.com> wrote:
>
>
>
> On 2018年07月04日 12:31, xiangxia.m.yue@gmail.com wrote:
> > From: Tonghao Zhang <xiangxia.m.yue@gmail.com>
> >
> > This patches improve the guest receive and transmit performance.
> > On the handle_tx side, we poll the sock receive queue at the same time.
> > handle_rx do that in the same way.
> >
> > For more performance report, see patch 4.
> >
> > v4 -> v5:
> > fix some issues
> >
> > v3 -> v4:
> > fix some issues
> >
> > v2 -> v3:
> > This patches are splited from previous big patch:
> > http://patchwork.ozlabs.org/patch/934673/
> >
> > Tonghao Zhang (4):
> > vhost: lock the vqs one by one
> > net: vhost: replace magic number of lock annotation
> > net: vhost: factor out busy polling logic to vhost_net_busy_poll()
> > net: vhost: add rx busy polling in tx path
> >
> > drivers/vhost/net.c | 108 ++++++++++++++++++++++++++++----------------------
> > drivers/vhost/vhost.c | 24 ++++-------
> > 2 files changed, 67 insertions(+), 65 deletions(-)
> >
>
> Hi, any progress on the new version?
>
> I plan to send a new series of packed virtqueue support of vhost. If you
> plan to send it soon, I can wait. Otherwise, I will send my series.
I rebase the codes. and find there is no improvement anymore, the
patches of makita may solve the problem. jason you may send your
patches, and I will do some research on busypoll.
> Thanks
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: [PATCH bpf-next v3 12/13] tools: libbpf: allow map reuse
From: Jakub Kicinski @ 2018-07-11 4:53 UTC (permalink / raw)
To: Andrey Ignatov; +Cc: alexei.starovoitov, daniel, oss-drivers, netdev
In-Reply-To: <20180711034535.GC52033@rdna-mbp>
On Tue, 10 Jul 2018 20:45:36 -0700, Andrey Ignatov wrote:
> Acked-by: Andrey Ignatov <rdna@fb.com>
Thank you! :)
> Thanks for all the changes Jakub! Sorry, it forced you to deal with
> strerror_r().
No worries, I already had issues with reallocarray(). Because we have
two reasons now the split seems more justified, and it's cleaner IMHO.
> One thing, I'm not really sure, is if there is a reason not to copy
> ifindex as well from the map that corresponds to passed fd. It's fine
> with me to follow-up separately though if it's needed.
To handle the ifindex correctly we would have to deal with net
namespaces. Note that ifindex comes with the pair of netns_* fields
in bpf_map_info. Netdev can also be moved to another namespace after
the information is cached in libbpf.
Right now there is no use for ifindex other than to populate the
attribute at creation time (where it always refer to current namespace).
I'd rather keep ifindex as a input only parameter until we have a clear
use for reading it, otherwise we have to decide on the semantics in the
dark and may bring in quite a bit of complexity for no good reason.
^ permalink raw reply
* Re: [PATCH net-next v5 0/4] net: vhost: improve performance when enable busyloop
From: Jason Wang @ 2018-07-11 5:12 UTC (permalink / raw)
To: Tonghao Zhang
Cc: mst, makita.toshiaki, virtualization,
Linux Kernel Network Developers
In-Reply-To: <CAMDZJNWqF95P1YBiu5X+gBbBOp2EVe380D2kzNmdes_4hBH3dw@mail.gmail.com>
On 2018年07月11日 11:49, Tonghao Zhang wrote:
> On Wed, Jul 11, 2018 at 10:56 AM Jason Wang <jasowang@redhat.com> wrote:
>>
>>
>> On 2018年07月04日 12:31, xiangxia.m.yue@gmail.com wrote:
>>> From: Tonghao Zhang <xiangxia.m.yue@gmail.com>
>>>
>>> This patches improve the guest receive and transmit performance.
>>> On the handle_tx side, we poll the sock receive queue at the same time.
>>> handle_rx do that in the same way.
>>>
>>> For more performance report, see patch 4.
>>>
>>> v4 -> v5:
>>> fix some issues
>>>
>>> v3 -> v4:
>>> fix some issues
>>>
>>> v2 -> v3:
>>> This patches are splited from previous big patch:
>>> http://patchwork.ozlabs.org/patch/934673/
>>>
>>> Tonghao Zhang (4):
>>> vhost: lock the vqs one by one
>>> net: vhost: replace magic number of lock annotation
>>> net: vhost: factor out busy polling logic to vhost_net_busy_poll()
>>> net: vhost: add rx busy polling in tx path
>>>
>>> drivers/vhost/net.c | 108 ++++++++++++++++++++++++++++----------------------
>>> drivers/vhost/vhost.c | 24 ++++-------
>>> 2 files changed, 67 insertions(+), 65 deletions(-)
>>>
>> Hi, any progress on the new version?
>>
>> I plan to send a new series of packed virtqueue support of vhost. If you
>> plan to send it soon, I can wait. Otherwise, I will send my series.
> I rebase the codes. and find there is no improvement anymore, the
> patches of makita may solve the problem. jason you may send your
> patches, and I will do some research on busypoll.
I see. Maybe you can try some bi-directional traffic.
Btw, lots of optimizations could be done for busy polling. E.g
integrating with host NAPI busy polling or a 100% busy polling
vhost_net. You're welcome to work or propose new ideas.
Thanks
>
>> Thanks
^ permalink raw reply
* Re: [PATCH rdma-next 0/9] Support mlx5 flow steering with RAW data
From: Leon Romanovsky @ 2018-07-11 5:43 UTC (permalink / raw)
To: Jason Gunthorpe, Saeed Mahameed
Cc: Doug Ledford, RDMA mailing list, Yishai Hadas, linux-netdev
In-Reply-To: <20180710182854.GA24311@ziepe.ca>
[-- Attachment #1: Type: text/plain, Size: 2176 bytes --]
On Tue, Jul 10, 2018 at 12:28:54PM -0600, Jason Gunthorpe wrote:
> On Sun, Jul 08, 2018 at 01:24:36PM +0300, Leon Romanovsky wrote:
> > From: Leon Romanovsky <leonro@mellanox.com>
> >
> > >From Yishai:
> >
> > This series introduces vendor create and destroy flow methods on the
> > uverbs flow object by using the KABI infra-structure.
> >
> > It's done in a way that enables the driver to get its specific device
> > attributes in a raw data to match its underlay specification while still
> > using the generic ib_flow object for cleanup and code sharing.
> >
> > In addition, a specific mlx5 matcher object and its create/destroy
> > methods were introduced. This object matches the underlay flow steering
> > mask specification and is used as part of mlx5 create flow input data.
> >
> > This series supports IB_QP/TIR as its flow steering destination as
> > applicable today via the ib_create_flow API, however, it adds also an
> > option to work with DEVX object which its destination can be both TIR
> > and flow table.
> >
> > Few changes were done in the mlx5 core layer to support forward
> > compatible for the device specification raw data and to support flow
> > table when the DEVX destination is used.
> >
> > As part of this series the default IB destroy handler
> > (i.e. uverbs_destroy_def_handler()) was exposed from IB core to be
> > used by the drivers and existing code was refactored to use it.
> >
> > Thanks
>
> > IB: Enable uverbs_destroy_def_handler to be used by drivers
>
> I applied this one
>
> > Yishai Hadas (9):
> > net/mlx5: Add forward compatible support for the FTE match data
> > net/mlx5: Add support for flow table destination number
> > IB/mlx5: Introduce flow steering matcher object
> > IB: Consider ib_flow creation by the KABI infrastructure
> > IB/mlx5: Introduce vendor create and destroy flow methods
> > IB/mlx5: Support adding flow steering rule by raw data
> > IB/mlx5: Add support for a flow table destination
> > IB/mlx5: Expose vendor flow trees
>
> The rest will need to be resent after the comments are addressed.
Jason, Saeed
Thanks for the comments, we will fix and resubmit.
>
> Thanks,
> Jason
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH net-next v19 0/8] sched: Add Common Applications Kept Enhanced (cake) qdisc
From: David Miller @ 2018-07-11 5:56 UTC (permalink / raw)
To: toke
Cc: netdev, gamanakis, peteheist, ycheng, ncardwell, dave.taht,
netfilter-devel, cake
In-Reply-To: <153089141290.14813.1010951705929696896.stgit@alrua-x1>
From: Toke Høiland-Jørgensen <toke@toke.dk>
Date: Fri, 06 Jul 2018 17:37:19 +0200
> This patch series adds the CAKE qdisc, and has been split up to ease
> review.
>
> I have attempted to split out each configurable feature into its own patch.
> The first commit adds the base shaper and packet scheduler, while
> subsequent commits add the optional features. The full userspace API and
> most data structures are included in this commit, but options not
> understood in the base version will be ignored.
>
> The result of applying the entire series is identical to the out of tree
> version that have seen extensive testing in previous deployments, most
> notably as an out of tree patch to OpenWrt. However, note that I have only
> compile tested the individual patches; so the whole series should be
> considered as a unit.
Ok, I decided to apply this even though there are still bits I'm not
%100 happy with.
I don't like the netfilter dependency at all.
You can get the NAT addresses in other ways as I've tried to suggest
in the past. Your scheme absolutely does not work with act_nat
in the packet scheduler, not any NAT done by XDP/eBPF programs.
^ permalink raw reply
* Re: [PATCH net-next] selftests: forwarding: mirror_lib: Tighten up VLAN capture
From: David Miller @ 2018-07-11 5:58 UTC (permalink / raw)
To: petrm; +Cc: netdev, linux-kselftest, shuah
In-Reply-To: <0fecbe018ff9a06a5f3686e3c4801b5005925019.1531072211.git.petrm@mellanox.com>
From: Petr Machata <petrm@mellanox.com>
Date: Sun, 08 Jul 2018 19:58:55 +0200
> The function do_test_span_vlan_dir_ips() is used for testing whether
> mirrored packets are VLAN-encapsulated. But since it only considers
> VLAN encapsulation, it may end up matching unmirrored ARP traffic as
> well. One consequence is a rare failure of mirror_gre_vlan_bridge_1q's
> test_gretap_untagged_egress. Decreasing ping cadence in mirror_test()
> makes the problem easily reproducible.
>
> Therefore tighten up the match criterion to only count those 802.1q
> packets where the next header is IP.
>
> Signed-off-by: Petr Machata <petrm@mellanox.com>
Applied.
^ permalink raw reply
* [PATCH] ipw2x00: remove redundant variables len, ret, reason and crypt
From: Colin King @ 2018-07-11 7:12 UTC (permalink / raw)
To: Stanislav Yakovlev, Kalle Valo, David S . Miller,
linux-wireless-u79uwXL29TY76Z2rM5mHXA
Cc: kernel-janitors-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
From: Colin Ian King <colin.king-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
Variables len, ret, reason and crypt are assigned values that
are never read, hence they are redundant and can be removed.
Note: For the variable ret, a return code is being assigned, but
this is not returned and 0 is currently being returned, I believe
this is OK.
Cleans up clang warnings:
warning: variable 'len' set but not used [-Wunused-but-set-variable]
variable 'ret' set but not used [-Wunused-but-set-variable]
warning: variable 'reason' set but not used [-Wunused-but-set-variable]
warning: variable 'crypt' set but not used [-Wunused-but-set-variable]
Signed-off-by: Colin Ian King <colin.king-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
---
drivers/net/wireless/intel/ipw2x00/ipw2100.c | 7 -------
drivers/net/wireless/intel/ipw2x00/libipw_wx.c | 2 --
2 files changed, 9 deletions(-)
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
index 1ad83ef5f202..910db46db6a1 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
@@ -5112,11 +5112,9 @@ static int ipw2100_disassociate_bssid(struct ipw2100_priv *priv)
.host_command_length = ETH_ALEN
};
int err;
- int len;
IPW_DEBUG_HC("DISASSOCIATION_BSSID\n");
- len = ETH_ALEN;
/* The Firmware currently ignores the BSSID and just disassociates from
* the currently associated AP -- but in the off chance that a future
* firmware does use the BSSID provided here, we go ahead and try and
@@ -7723,7 +7721,6 @@ static int ipw2100_wx_get_auth(struct net_device *dev,
struct libipw_device *ieee = priv->ieee;
struct lib80211_crypt_data *crypt;
struct iw_param *param = &wrqu->param;
- int ret = 0;
switch (param->flags & IW_AUTH_INDEX) {
case IW_AUTH_WPA_VERSION:
@@ -7733,7 +7730,6 @@ static int ipw2100_wx_get_auth(struct net_device *dev,
/*
* wpa_supplicant will control these internally
*/
- ret = -EOPNOTSUPP;
break;
case IW_AUTH_TKIP_COUNTERMEASURES:
@@ -7801,9 +7797,6 @@ static int ipw2100_wx_set_mlme(struct net_device *dev,
{
struct ipw2100_priv *priv = libipw_priv(dev);
struct iw_mlme *mlme = (struct iw_mlme *)extra;
- __le16 reason;
^ permalink raw reply related
* [PATCH] iwlegacy: remove several redundant variables
From: Colin King @ 2018-07-11 7:42 UTC (permalink / raw)
To: Stanislaw Gruszka, Kalle Valo, David S . Miller,
linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
Cc: kernel-janitors-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
From: Colin Ian King <colin.king-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
Variables id, unicast, write, conf, a_band, accum_tx and ucode are
assigned a value but it is never read, hence they are redundant and
can be removed.
Cleans up clang warnings:
warning: variable 'id' set but not used [-Wunused-but-set-variable]
warning: variable 'unicast' set but not used [-Wunused-but-set-variable]
warning: variable 'write' set but not used [-Wunused-but-set-variable]
warning: variable 'conf' set but not used [-Wunused-but-set-variable]
warning: variable 'a_band' set but not used [-Wunused-but-set-variable]
warning: variable 'tx' set but not used [-Wunused-but-set-variable]
warning: variable 'accum_tx' set but not used [-Wunused-but-set-variable]
warning: variable 'ucode' set but not used [-Wunused-but-set-variable]
Signed-off-by: Colin Ian King <colin.king-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
---
drivers/net/wireless/intel/iwlegacy/3945-mac.c | 10 ----------
drivers/net/wireless/intel/iwlegacy/3945.c | 2 --
drivers/net/wireless/intel/iwlegacy/4965-mac.c | 6 ------
3 files changed, 18 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlegacy/3945-mac.c b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
index 62a9794f952b..57e3b6cca234 100644
--- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c
+++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
@@ -476,8 +476,6 @@ il3945_tx_skb(struct il_priv *il,
int txq_id = skb_get_queue_mapping(skb);
u16 len, idx, hdr_len;
u16 firstlen, secondlen;
- u8 id;
- u8 unicast;
u8 sta_id;
u8 tid = 0;
__le16 fc;
@@ -496,9 +494,6 @@ il3945_tx_skb(struct il_priv *il,
goto drop_unlock;
}
- unicast = !is_multicast_ether_addr(hdr->addr1);
- id = 0;
-
fc = hdr->frame_control;
#ifdef CONFIG_IWLEGACY_DEBUG
@@ -957,10 +952,8 @@ il3945_rx_queue_restock(struct il_priv *il)
struct list_head *element;
struct il_rx_buf *rxb;
unsigned long flags;
- int write;
spin_lock_irqsave(&rxq->lock, flags);
- write = rxq->write & ~0x7;
while (il_rx_queue_space(rxq) > 0 && rxq->free_count) {
/* Get next free Rx buffer, remove from free list */
element = rxq->rx_free.next;
@@ -2725,7 +2718,6 @@ void
il3945_post_associate(struct il_priv *il)
{
int rc = 0;
- struct ieee80211_conf *conf = NULL;
if (!il->vif || !il->is_open)
return;
@@ -2738,8 +2730,6 @@ il3945_post_associate(struct il_priv *il)
il_scan_cancel_timeout(il, 200);
- conf = &il->hw->conf;
-
il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
il3945_commit_rxon(il);
diff --git a/drivers/net/wireless/intel/iwlegacy/3945.c b/drivers/net/wireless/intel/iwlegacy/3945.c
index dbf164d48ed3..3e568ce2fb20 100644
--- a/drivers/net/wireless/intel/iwlegacy/3945.c
+++ b/drivers/net/wireless/intel/iwlegacy/3945.c
@@ -1634,7 +1634,6 @@ il3945_hw_reg_set_txpower(struct il_priv *il, s8 power)
{
struct il_channel_info *ch_info;
s8 max_power;
- u8 a_band;
u8 i;
if (il->tx_power_user_lmt == power) {
@@ -1650,7 +1649,6 @@ il3945_hw_reg_set_txpower(struct il_priv *il, s8 power)
for (i = 0; i < il->channel_count; i++) {
ch_info = &il->channel_info[i];
- a_band = il_is_channel_a_band(ch_info);
/* find minimum power of all user and regulatory constraints
* (does not consider h/w clipping limitations) */
diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
index 562e94870a9c..280cd8ae1696 100644
--- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
@@ -1338,15 +1338,12 @@ il4965_accumulative_stats(struct il_priv *il, __le32 * stats)
u32 *accum_stats;
u32 *delta, *max_delta;
struct stats_general_common *general, *accum_general;
- struct stats_tx *tx, *accum_tx;
prev_stats = (__le32 *) &il->_4965.stats;
accum_stats = (u32 *) &il->_4965.accum_stats;
size = sizeof(struct il_notif_stats);
general = &il->_4965.stats.general.common;
accum_general = &il->_4965.accum_stats.general.common;
- tx = &il->_4965.stats.tx;
- accum_tx = &il->_4965.accum_stats.tx;
delta = (u32 *) &il->_4965.delta_stats;
max_delta = (u32 *) &il->_4965.max_delta;
@@ -4784,7 +4781,6 @@ static void
il4965_ucode_callback(const struct firmware *ucode_raw, void *context)
{
struct il_priv *il = context;
- struct il_ucode_header *ucode;
int err;
struct il4965_firmware_pieces pieces;
const unsigned int api_max = il->cfg->ucode_api_max;
@@ -4814,8 +4810,6 @@ il4965_ucode_callback(const struct firmware *ucode_raw, void *context)
}
/* Data from ucode file: header followed by uCode images */
- ucode = (struct il_ucode_header *)ucode_raw->data;
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox