* Re: [PATCH net-next 0/2] net: sched: act_ctinfo: fixes
From: David Miller @ 2019-06-17 21:01 UTC (permalink / raw)
To: ldir; +Cc: netdev
In-Reply-To: <20190617100327.24796-1-ldir@darbyshire-bryant.me.uk>
From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Date: Mon, 17 Jun 2019 11:03:25 +0100
> This is first attempt at sending a small series. Order is important
> because one bug (policy validation) prevents us from encountering the
> more important 'OOPS' generating bug in action creation. Fix the OOPS
> first.
>
> Confession time: Until very recently, development of this module has
> been done on 'net-next' tree to 'clean compile' level with run-time
> testing on backports to 4.14 & 4.19 kernels under openwrt. It turns out
> that sched: action: based code has been under more active change than I
> realised.
>
> During the back & forward porting during development & testing, the
> critical ACT_P_CREATED return code got missed despite being in the 4.14
> & 4.19 backports. I have now gone through the init functions, using
> act_csum as reference with a fine toothed comb and am happy they do the
> same things.
>
> This issue hadn't been caught till now due to another issue caused by
> new strict nla_parse_nested function failing parsing validation before
> action creation.
>
> Thanks to Marcelo Leitner <marcelo.leitner@gmail.com> for flagging
> extack deficiency (fixed in 733f0766c3de sched: act_ctinfo: use extack
> error reporting) which led to b424e432e770 ("netlink: add validation of
> NLA_F_NESTED flag") and 8cb081746c03 ("netlink: make validation more
> configurable for future strictness”) which led to the policy validation
> fix, which then led to the action creation fix both contained in this
> series.
>
> If I ever get to a developer conference please feel free to
> tar/feather/apply cone of shame.
:-) In kernel networking development we prefer brown paper bags over
cones of shame, just FYI :) :) :)
Series applied, thanks.
^ permalink raw reply
* Re: [RFC PATCH bpf-next 6/8] libbpf: allow specifying map definitions using BTF
From: Andrii Nakryiko @ 2019-06-17 20:59 UTC (permalink / raw)
To: Lorenz Bauer
Cc: Andrii Nakryiko, Networking, bpf, Alexei Starovoitov,
Daniel Borkmann, Kernel Team
In-Reply-To: <CACAyw9_Yr=pmvCRYsVHoQBrH7qBwmcaXZezmqafwJTxaCmDf6A@mail.gmail.com>
On Mon, Jun 17, 2019 at 2:07 AM Lorenz Bauer <lmb@cloudflare.com> wrote:
>
> On Thu, 6 Jun 2019 at 23:35, Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote:
> >
> > On Thu, Jun 6, 2019 at 9:43 AM Lorenz Bauer <lmb@cloudflare.com> wrote:
> > >
> > > Thanks for sending this RFC! For me, the biggest draw is that map-in-map
> > > would be so much nicer to use, plus automatic dumping of map values.
> > >
> > > Others on the thread have raised this point already: not everybody lives
> > > on the bleeding edge or can control all of their dependencies. To me this means
> > > that having a good compatibility story is paramount. I'd like to have very clear
> > > rules how the presence / absence of fields is handled.
> >
> > I think that discussion was more about selftests being switched to
> > BTF-defined maps rather than BPF users having to switch to latest
> > compiler. struct bpf_map_def is still supported for those who can't
> > use clang that supports BTF_KIND_VAR/BTF_KIND_DATASEC.
> > So I don't think this enforces anyone to switch compiler, but
> > certainly incentivizes them :)
> >
> > >
> > > For example:
> > > - Fields that are present but not understood are an error. This makes
> > > sense because
> > > the user can simply omit the field in their definition if they do
> > > not use it. It's also necessary
> > > to preserve the freedom to add new fields in the future without
> > > risking user breakage.
> >
> > So you are arguing for strict-by-default behavior. It's fine by me,
> > but exactly that strict-by-default behavior is the problem with BTF
> > extensivility, that you care a lot about. You are advocating for
> > skipping unknown BTF types (if it was possible), which is directly
> > opposite to strict-by-default behavior. I have no strong preference
> > here, but given amount of problem (and how many times we missed this
> > problem in the past) w/ introducing new BTF feature and then
> > forgetting about doing something for older kernels, kind of makes me
> > lean towards skip-and-log behavior. But I'm happy to support both
> > (through flags) w/ strict by default.
>
> In my mind, BPF loaders should be able to pass through BTF to the kernel
> as a binary blob as much as possible. That's why I want the format to
> be "self describing". Compatibility then becomes a question of: what
> feature are you using on which kernel. The kernel itself can then still be
> strict-by-default or what have you.
That would work in ideal world, where kernel is updated frequently
(and BTF is self-describing, which it is not). In practice, though,
libbpf is far more up-to-date and lends its hand on "sanitizing" .BTF
from kernel-unsupported features (so far we manage to pull this off
very reasonably). If you have a good proposal how to make .BTF
self-describing, that would be great!
>
> >
> > > - If libbpf adds support for a new field, it must be optional. Seems
> > > like this is what current
> > > map extensions already do, so maybe a no-brainer.
> >
> > Yeah, of course.
> >
> > >
> > > Somewhat related to this: I really wish that BTF was self-describing,
> > > e.g. possible
> > > to parse without understanding all types. I mentioned this in another
> > > thread of yours,
> > > but the more we add features where BTF is required the more important it becomes
> > > IMO.
> >
> > I relate, but have no new and better solution than previously
> > discussed :) We should try to add new stuff to .BTF.ext as much as
> > possible, which is self-describing.
> >
> > >
> > > Finally, some nits inline:
> > >
> > > On Fri, 31 May 2019 at 21:22, Andrii Nakryiko <andriin@fb.com> wrote:
> > > >
> > > > The outline of the new map definition (short, BTF-defined maps) is as follows:
> > > > 1. All the maps should be defined in .maps ELF section. It's possible to
> > > > have both "legacy" map definitions in `maps` sections and BTF-defined
> > > > maps in .maps sections. Everything will still work transparently.
> > >
> > > I'd prefer using a new map section "btf_maps" or whatever. No need to
> > > worry about code that deals with either type.
> >
> > We do use new map section. Its ".maps" vs "maps". Difference is
> > subtle, but ".maps" looks a bit more "standardized" than "btf_maps" to
> > me (and hopefully, eventually no one will use "maps" anymore :) ).
>
> Phew, spotting that difference is night impossible IMO.
Eventually "maps" should die off, as people switch from bpf_map_def to
to BTF-defined maps in .maps. Libbpf itself can just provide a macro
hiding all that, something like:
#define BPF_MAP __attribute__((section(".maps"), used))
>
> >
> > >
> > > > 3. Key/value fields should be **a pointer** to a type describing
> > > > key/value. The pointee type is assumed (and will be recorded as such
> > > > and used for size determination) to be a type describing key/value of
> > > > the map. This is done to save excessive amounts of space allocated in
> > > > corresponding ELF sections for key/value of big size.
> > >
> > > My biggest concern with the pointer is that there are cases when we want
> > > to _not_ use a pointer, e.g. your proposal for map in map and tail calling.
> > > There we need value to be a struct, an array, etc. The burden on the user
> > > for this is very high.
> >
> > Well, map-in-map is still a special case and whichever syntax we go
> > with, it will need to be of slightly different syntax to distinguish
> > between those cases. Initialized maps fall into similar category,
> > IMHO.
>
> I agree with you, the syntax probably has to be different. I'd just like it to
> differ by more than a "*" in the struct definition, because that is too small
> to notice.
So let's lay out how it will be done in practice:
1. Simple map w/ custom key/value
struct my_key { ... };
struct my_value { ... };
struct {
__u32 type;
__u32 max_entries;
struct my_key *key;
struct my_value *value;
} my_simple_map BPF_MAP = {
.type = BPF_MAP_TYPE_ARRAY,
.max_entries = 16,
};
2. Now map-in-map:
struct {
__u32 type;
__u32 max_entries;
struct my_key *key;
struct {
__u32 type;
__u32 max_entries;
__u64 *key;
struct my_value *value;
} value;
} my_map_in_map BPF_MAP = {
.type = BPF_MAP_TYPE_HASH_OF_MAPS,
.max_entries = 16,
.value = {
.type = BPF_MAP_TYPE_ARRAY,
.max_entries = 100,
},
};
It's clearly hard to misinterpret inner map definition for a custom
anonymous struct type, right?
>
> >
> > Embedding full value just to capture type info/size is unacceptable,
> > as we have use cases that cause too big ELF size increase, which will
> > prevent users from switching to this.
> >
> > >
> > > > 4. As some maps disallow having BTF type ID associated with key/value,
> > > > it's possible to specify key/value size explicitly without
> > > > associating BTF type ID with it. Use key_size and value_size fields
> > > > to do that (see example below).
> > >
> > > Why not just make them use the legacy map?
> >
> > For completeness' sake at the least. E.g., what if you want to use
> > map-in-map, where inner map is stackmap or something like that, which
> > requires key_size/value_size? I think we all agree that it's better if
> > application uses just one style, instead of a mix of both, right?
>
> I kind of assumed that BTF support for those maps would at some point
> appear, maybe I should have checked that.
It will. Current situation with maps not supporting specifying BTF for
key and/or value looks more like a bug, than feature and we should fix
that. But even if we fix it today, kernels are updated much slower
than libbpf, so by not supporting key_size/value_size, we force people
to get stuck with legacy bpf_map_def for a really long time.
>
> > Btw, for map cases where map key can be arbitrary, but value is FD or
> > some other opaque value, libbpf can automatically "derive" value size
> > and still capture key type. I haven't done that, but it's very easy to
> > do (and also we can keep adding per-map-type checks/niceties, to help
> > users understand what's wrong with their map definition, instead of
> > getting EINVAL from kernel on map creation).
> >
> > >
> > > --
> > > Lorenz Bauer | Systems Engineer
> > > 6th Floor, County Hall/The Riverside Building, SE1 7PB, UK
> > >
> > > www.cloudflare.com
>
>
>
> --
> Lorenz Bauer | Systems Engineer
> 6th Floor, County Hall/The Riverside Building, SE1 7PB, UK
>
> www.cloudflare.com
^ permalink raw reply
* Re: [PATCH net-next] vhost_net: disable zerocopy by default
From: David Miller @ 2019-06-17 20:58 UTC (permalink / raw)
To: jasowang; +Cc: mst, kvm, virtualization, netdev, linux-kernel, huhai
In-Reply-To: <20190617092054.12299-1-jasowang@redhat.com>
From: Jason Wang <jasowang@redhat.com>
Date: Mon, 17 Jun 2019 05:20:54 -0400
> Vhost_net was known to suffer from HOL[1] issues which is not easy to
> fix. Several downstream disable the feature by default. What's more,
> the datapath was split and datacopy path got the support of batching
> and XDP support recently which makes it faster than zerocopy part for
> small packets transmission.
>
> It looks to me that disable zerocopy by default is more
> appropriate. It cold be enabled by default again in the future if we
> fix the above issues.
>
> [1] https://patchwork.kernel.org/patch/3787671/
>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
Applied, thanks Jason.
^ permalink raw reply
* Re: [PATCH v3] net: ipv4: move tcp_fastopen server side code to SipHash library
From: David Miller @ 2019-06-17 20:57 UTC (permalink / raw)
To: eric.dumazet
Cc: ard.biesheuvel, netdev, linux-crypto, herbert, ebiggers, edumazet,
kuznet, yoshfuji, jbaron, cpaasch, David.Laight, ycheng
In-Reply-To: <e1c4c9b6-3668-106a-69ef-7ef6c016a5f6@gmail.com>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Mon, 17 Jun 2019 10:00:28 -0700
> All our fastopen packetdrill tests pass (after I changed all the cookie values in them)
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
I'm going to apply this to net-next, I want it to sit there for a
while.
Thanks.
^ permalink raw reply
* Re: [PATCH] bpf: optimize constant blinding
From: Alexei Starovoitov @ 2019-06-17 20:53 UTC (permalink / raw)
To: Jiong Wang
Cc: Edward Cree, Alexei Starovoitov, Andrii Nakryiko, Naveen N. Rao,
Daniel Borkmann, bpf, Network Development, Michael Ellerman,
Jakub Kicinski
In-Reply-To: <877e9kgd39.fsf@netronome.com>
On Mon, Jun 17, 2019 at 1:40 PM Jiong Wang <jiong.wang@netronome.com> wrote:
>
> After digest Alexei and Andrii's reply, I still don't see the need to turn
> branch target into list, and I am not sure whether pool based list sound
> good? it saves size, resize pool doesn't invalid allocated node (the offset
> doesn't change) but requires one extra addition to calculate the pointer.
I don't think it worth to do a pool to accelerate kmalloc.
I doubt it will be faster either.
^ permalink raw reply
* Re: [PATCH] bpf: optimize constant blinding
From: Jiong Wang @ 2019-06-17 20:40 UTC (permalink / raw)
To: Edward Cree, Alexei Starovoitov, Andrii Nakryiko
Cc: Jiong Wang, Alexei Starovoitov, Naveen N. Rao, Daniel Borkmann,
bpf, Network Development, Michael Ellerman, Jakub Kicinski
In-Reply-To: <58d86352-4989-38d6-666b-5e932df9ed46@solarflare.com>
Edward Cree writes:
> On 17/06/2019 20:59, Jiong Wang wrote:
>> Edward Cree writes:
>>
>>> On 14/06/2019 16:13, Jiong Wang wrote:
>>>> Just an update and keep people posted.
>>>>
>>>> Working on linked list based approach, the implementation looks like the
>>>> following, mostly a combine of discussions happened and Naveen's patch,
>>>> please feel free to comment.
>>>>
>>>> - Use the reserved opcode 0xf0 with BPF_ALU as new pseudo insn code
>>>> BPF_LIST_INSN. (0xf0 is also used with BPF_JMP class for tail call).
>>>>
>>>> - Introduce patch pool into bpf_prog->aux to keep all patched insns.
>>> It's not clear to me what the point of the patch pool is, rather than just
>>> doing the patch straight away.
>> I used pool because I was thinking insn to be patched could be high
>> percentage, so doing lots of alloc call is going to be less efficient? so
>> allocate a big pool, and each time when creating new patch node, allocate
>> it from the pool directly. Node is addressed using pool_base + offset, each
>> node only need to keep offset.
> Good idea; but in that case it doesn't need to be a pool of patches (storing
> their prev and next), just a pool of insns. I.e. struct bpf_insn pool[many];
> then in orig prog when patching an insn replace it with BPF_LIST_INSN. If
> we later decide to patch an insn within a patch, we can replace it (i.e. the
> entry in bpf_insn_pool) with another BPF_LIST_INSN pointing to some later bit
> of the pool, then we just have a little bit of recursion at linearise time.
> Does that work?
I feel it is not going to work well. What I have proposed initially is
something similar, except when we are patching an insn within a patch (do
exist, for example zext insertion will apply to some patched alu insn
inserted in ctx convert pass), then we split the patch, this then makes the
data structures used in two shapes,
1. original prog->insnsi is still maintained as array.
2. if one insn is BPF_LIST_INSN, then it is a list, and could traverse it
using pool_base + insn.imm = list head.
But then there is data structure inconsistent, so now when doing insn
traversal we need something like:
for (idx = 0; idx < insn_cnt; idx++) {
if (insns[idx] is not BPF_LIST_INSN) {
do_insn(...)
}
else if (insns[idx] is BPF_LIST_INSN) {
list = pool_base + insn.imm;
while (list) {
insn = list_head->insn;
do_insn(...)
list = pool_base + list->next;
}
}
}
Code logic inside convert_ctx_accesses/fixup_bpf_call etc needs to be
re-factored out into a separate function do_NNN so it could be called
in above logic.
Now if we don't split patch when patch an insn inside patch, instead, if we
replace the patched insn using what you suggested, then the logic looks to
me becomes even more complex, something like
for (idx = 0; idx < insn_cnt; idx++) {
if (insns[idx] is not BPF_LIST_INSN) {
do_insn(...)
}
else if (insns[idx] is BPF_LIST_INSN) {
list = pool_base + insn.imm;
while (list) {
insn = list_head->insn;
if (insn is BF_LIST_INSN) {
sub_list = ...
while ()
do_insn()
continue;
}
do_insn(...)
list = pool_base + list->next;
}
}
}
So, I am thinking what Alexei and Andrii suggested make sense, just use
single data structure (singly linked list) to represent everything, so the
insn traversal etc could be simple, but I am considering it is better to
still base the list on top of the pool infrastructure mentioned?
I have somethingn like the following:
+struct bpf_list_insn {
+ struct bpf_insn insn;
+ u32 next;
+};
struct bpf_prog_aux {:
+ struct {
+ struct bpf_list_insn *pool;
+ u32 size;
+ u32 used;
+ };
Whenever you want to do intensive patching work you could call
bpf_patch_init to setup the pool, the setup including:
1. convert the original prog->insnsi into a list of bpf_list_insn.
next is index into the pool, so for those initial insnsi, they are
1, 2, 3, 4, 5, ...
Then when doing patching, just allocate new slot from the pool, and link
them into the list.
When patching finished call bpf_patch_fini to do lineraize, could use the
same algo in Navee's patch.
After digest Alexei and Andrii's reply, I still don't see the need to turn
branch target into list, and I am not sure whether pool based list sound
good? it saves size, resize pool doesn't invalid allocated node (the offset
doesn't change) but requires one extra addition to calculate the pointer.
>
> -Ed
^ permalink raw reply
* Re: [PATCH net-next v4 1/3] hinic: add rss support
From: David Miller @ 2019-06-17 20:34 UTC (permalink / raw)
To: xuechaojing
Cc: linux-kernel, netdev, luoshaokai, cloud.wangxiaoyun, chiqijun,
wulike1
In-Reply-To: <20190617054601.3056-2-xuechaojing@huawei.com>
From: Xue Chaojing <xuechaojing@huawei.com>
Date: Mon, 17 Jun 2019 05:45:59 +0000
> +static int hinic_rss_init(struct hinic_dev *nic_dev)
> +{
> + u8 default_rss_key[HINIC_RSS_KEY_SIZE] = { 0 };
> + u32 indir_tbl[HINIC_RSS_INDIR_SIZE] = { 0 };
> + u8 tmpl_idx = nic_dev->rss_tmpl_idx;
> + int err, i;
> +
> + netdev_rss_key_fill(default_rss_key, sizeof(default_rss_key));
Since netdev_rss_key_fill() fills the entire object, you don't need the
variable initializer for default_rss_key here, please remove it.
> +int hinic_rss_set_indir_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,
> + const u32 *indir_table)
> +{
> + for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) {
> + indir_tbl->entry[i] = (u8)(*(indir_table + i));
Please index the array normally using "indir_table[i]", I also suspect
the u8 cast is also unnecessary.
^ permalink raw reply
* Re: [PATCH net-next v3 0/3] UDP GSO audit tests
From: Willem de Bruijn @ 2019-06-17 20:29 UTC (permalink / raw)
To: Fred Klassen
Cc: David S. Miller, Network Development, LKML, linux-kselftest,
Willem de Bruijn
In-Reply-To: <20190617190837.13186-1-fklassen@appneta.com>
On Mon, Jun 17, 2019 at 3:09 PM Fred Klassen <fklassen@appneta.com> wrote:
>
> Updates to UDP GSO selftests ot optionally stress test CMSG
> subsytem, and report the reliability and performance of both
> TX Timestamping and ZEROCOPY messages.
>
> Fred Klassen (3):
> net/udpgso_bench_tx: options to exercise TX CMSG
> net/udpgso_bench.sh add UDP GSO audit tests
> net/udpgso_bench.sh test fails on error
>
> tools/testing/selftests/net/udpgso_bench.sh | 52 ++++-
> tools/testing/selftests/net/udpgso_bench_tx.c | 291 ++++++++++++++++++++++++--
> 2 files changed, 327 insertions(+), 16 deletions(-)
>
> --
For the series:
Acked-by: Willem de Bruijn <willemb@google.com>
^ permalink raw reply
* Re: [net-next] tipc: include retrans failure detection for unicast
From: David Miller @ 2019-06-17 20:29 UTC (permalink / raw)
To: tuong.t.lien; +Cc: jon.maloy, maloy, ying.xue, netdev, tipc-discussion
In-Reply-To: <20190617051542.4133-1-tuong.t.lien@dektech.com.au>
From: Tuong Lien <tuong.t.lien@dektech.com.au>
Date: Mon, 17 Jun 2019 12:15:42 +0700
> In patch series, commit 9195948fbf34 ("tipc: improve TIPC throughput by
> Gap ACK blocks"), as for simplicity, the repeated retransmit failures'
> detection in the function - "tipc_link_retrans()" was kept there for
> broadcast retransmissions only.
>
> This commit now reapplies this feature for link unicast retransmissions
> that has been done via the function - "tipc_link_advance_transmq()".
>
> Also, the "tipc_link_retrans()" is renamed to "tipc_link_bc_retrans()"
> as it is used only for broadcast.
>
> Acked-by: Jon Maloy <jon.maloy@ericsson.se>
> Signed-off-by: Tuong Lien <tuong.t.lien@dektech.com.au>
Applied, thank you.
^ permalink raw reply
* Re: [PATCHv2 net-next] team: add ethtool get_link_ksettings
From: David Miller @ 2019-06-17 20:23 UTC (permalink / raw)
To: liuhangbin; +Cc: netdev, jiri
In-Reply-To: <20190617013255.27324-1-liuhangbin@gmail.com>
From: Hangbin Liu <liuhangbin@gmail.com>
Date: Mon, 17 Jun 2019 09:32:55 +0800
> Like bond, add ethtool get_link_ksettings to show the total speed.
>
> v2: no update, just repost.
>
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Applied, thank you.
^ permalink raw reply
* Re: [PATCH net v4] net/udp_gso: Allow TX timestamp with UDP GSO
From: Willem de Bruijn @ 2019-06-17 20:20 UTC (permalink / raw)
To: Fred Klassen; +Cc: David S. Miller, Network Development, LKML, Willem de Bruijn
In-Reply-To: <20190617190507.12730-1-fklassen@appneta.com>
On Mon, Jun 17, 2019 at 3:05 PM Fred Klassen <fklassen@appneta.com> wrote:
>
> Fixes an issue where TX Timestamps are not arriving on the error queue
> when UDP_SEGMENT CMSG type is combined with CMSG type SO_TIMESTAMPING.
> This can be illustrated with an updated updgso_bench_tx program which
> includes the '-T' option to test for this condition. It also introduces
> the '-P' option which will call poll() before reading the error queue.
>
> ./udpgso_bench_tx -4ucTPv -S 1472 -l2 -D 172.16.120.18
> poll timeout
> udp tx: 0 MB/s 1 calls/s 1 msg/s
>
> The "poll timeout" message above indicates that TX timestamp never
> arrived.
>
> This patch preserves tx_flags for the first UDP GSO segment. Only the
> first segment is timestamped, even though in some cases there may be
> benefital in timestamping both the first and last segment.
>
> Factors in deciding on first segment timestamp only:
>
> - Timestamping both first and last segmented is not feasible. Hardware
> can only have one outstanding TS request at a time.
>
> - Timestamping last segment may under report network latency of the
> previous segments. Even though the doorbell is suppressed, the ring
> producer counter has been incremented.
>
> - Timestamping the first segment has the upside in that it reports
> timestamps from the application's view, e.g. RTT.
>
> - Timestamping the first segment has the downside that it may
> underreport tx host network latency. It appears that we have to pick
> one or the other. And possibly follow-up with a config flag to choose
> behavior.
>
> v2: Remove tests as noted by Willem de Bruijn <willemb@google.com>
> Moving tests from net to net-next
>
> v3: Update only relevant tx_flag bits as per
> Willem de Bruijn <willemb@google.com>
>
> v4: Update comments and commit message as per
> Willem de Bruijn <willemb@google.com>
>
> Fixes: ee80d1ebe5ba ("udp: add udp gso")
> Signed-off-by: Fred Klassen <fklassen@appneta.com>
Acked-by: Willem de Bruijn <willemb@google.com>
^ permalink raw reply
* Re: [PATCH rdma-next v1 0/4] Expose ENCAP mode to mlx5_ib
From: Doug Ledford @ 2019-06-17 20:18 UTC (permalink / raw)
To: Leon Romanovsky, Jason Gunthorpe
Cc: RDMA mailing list, Maor Gottlieb, Mark Bloch, Parav Pandit,
Petr Vorel, Saeed Mahameed, linux-netdev, Jiri Pirko
In-Reply-To: <20190616124357.GH4694@mtr-leonro.mtl.com>
[-- Attachment #1: Type: text/plain, Size: 1298 bytes --]
On Sun, 2019-06-16 at 12:44 +0000, Leon Romanovsky wrote:
> On Wed, Jun 12, 2019 at 03:20:10PM +0300, Leon Romanovsky wrote:
> > From: Leon Romanovsky <leonro@mellanox.com>
> >
> > Changelog v0->v1:
> > * Added patch to devlink to use declared enum for encap mode
> > instead of u8
> > * Constify input argumetn to encap mode function
> > * fix encap variable type to be boolean
> >
> > -----------------------------------------------------------------
> > ----
> > Hi,
> >
> > This is short series from Maor to expose and use enacap mode inside
> > mlx5_ib.
> >
> > Thanks
> >
> > Leon Romanovsky (1):
> > net/mlx5: Declare more strictly devlink encap mode
> >
> > Maor Gottlieb (3):
> > net/mlx5: Expose eswitch encap mode
>
> Those two applied to mlx5-next
> 82b11f071936 net/mlx5: Expose eswitch encap mode
> 98fdbea55037 net/mlx5: Declare more strictly devlink encap mode
>
> > RDMA/mlx5: Consider eswitch encap mode
> > RDMA/mlx5: Enable decap and packet reformat on FDB
>
> Doug, Jason
>
> Can you please take those two patches in addition to latest mlx5-
> next?
Done, thanks.
--
Doug Ledford <dledford@redhat.com>
GPG KeyID: B826A3330E572FDD
Key fingerprint = AE6B 1BDA 122B 23B4 265B 1274 B826 A333 0E57
2FDD
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH] bpf: optimize constant blinding
From: Edward Cree @ 2019-06-17 20:11 UTC (permalink / raw)
To: Jiong Wang
Cc: Alexei Starovoitov, Naveen N. Rao, Daniel Borkmann, bpf,
Network Development, Michael Ellerman, Jakub Kicinski
In-Reply-To: <878su0geyt.fsf@netronome.com>
On 17/06/2019 20:59, Jiong Wang wrote:
> Edward Cree writes:
>
>> On 14/06/2019 16:13, Jiong Wang wrote:
>>> Just an update and keep people posted.
>>>
>>> Working on linked list based approach, the implementation looks like the
>>> following, mostly a combine of discussions happened and Naveen's patch,
>>> please feel free to comment.
>>>
>>> - Use the reserved opcode 0xf0 with BPF_ALU as new pseudo insn code
>>> BPF_LIST_INSN. (0xf0 is also used with BPF_JMP class for tail call).
>>>
>>> - Introduce patch pool into bpf_prog->aux to keep all patched insns.
>> It's not clear to me what the point of the patch pool is, rather than just
>> doing the patch straight away.
> I used pool because I was thinking insn to be patched could be high
> percentage, so doing lots of alloc call is going to be less efficient? so
> allocate a big pool, and each time when creating new patch node, allocate
> it from the pool directly. Node is addressed using pool_base + offset, each
> node only need to keep offset.
Good idea; but in that case it doesn't need to be a pool of patches (storing
their prev and next), just a pool of insns. I.e. struct bpf_insn pool[many];
then in orig prog when patching an insn replace it with BPF_LIST_INSN. If
we later decide to patch an insn within a patch, we can replace it (i.e. the
entry in bpf_insn_pool) with another BPF_LIST_INSN pointing to some later bit
of the pool, then we just have a little bit of recursion at linearise time.
Does that work?
-Ed
^ permalink raw reply
* Re: [PATCH net] hvsock: fix epollout hang from race condition
From: David Miller @ 2019-06-17 20:04 UTC (permalink / raw)
To: sunilmut
Cc: decui, kys, haiyangz, sthemmin, sashal, mikelley, netdev,
linux-hyperv, linux-kernel
In-Reply-To: <MW2PR2101MB11168BA3D46BEC843D694E04C0EB0@MW2PR2101MB1116.namprd21.prod.outlook.com>
From: Sunil Muthuswamy <sunilmut@microsoft.com>
Date: Mon, 17 Jun 2019 19:27:45 +0000
> The patch does not change at all. So, I was hoping we could reapply
> it. But, I have resubmitted the patch. Thanks.
It's easy for me to track things if you just resubmit the patch.
That's why I ask for things to be done this way, it helps my workflow
a lot.
Thank you.
^ permalink raw reply
* Re: WARNING in bpf_prog_kallsyms_find
From: syzbot @ 2019-06-17 20:00 UTC (permalink / raw)
To: ast, bpf, daniel, davem, hawk, jakub.kicinski, john.fastabend,
kafai, linux-kernel, netdev, songliubraving, syzkaller-bugs,
xdp-newbies, yhs
In-Reply-To: <000000000000a8fa360588580820@google.com>
syzbot has found a reproducer for the following crash on:
HEAD commit: a125097c Add linux-next specific files for 20190617
git tree: linux-next
console output: https://syzkaller.appspot.com/x/log.txt?x=130e3881a00000
kernel config: https://syzkaller.appspot.com/x/.config?x=f5fffe6c898291ba
dashboard link: https://syzkaller.appspot.com/bug?extid=89d1ce6e80218a6192d8
compiler: gcc (GCC) 9.0.0 20181231 (experimental)
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=16ee6121a00000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=174911aea00000
IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+89d1ce6e80218a6192d8@syzkaller.appspotmail.com
WARNING: CPU: 0 PID: 2952 at kernel/bpf/core.c:851 bpf_jit_free+0x157/0x1b0
Kernel panic - not syncing: panic_on_warn set ...
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
Call Trace:
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x172/0x1f0 lib/dump_stack.c:113
panic+0x2cb/0x744 kernel/panic.c:219
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#1] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075f850 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075f890 R08: ffff8880a073c600 R09: ffffed1015d06c70
R10: ffffed1015d06c6f R11: ffff8880ae83637b R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffffff R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#2] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075f378 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075f3b8 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffffff R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#3] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075ee98 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075eed8 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#4] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075e9b8 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075e9f8 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#5] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075e4d8 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075e518 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#6] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075dff8 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075e038 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#7] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075db18 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075db58 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#8] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075d638 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075d678 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#9] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075d158 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075d198 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#10] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075cc78 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075ccb8 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#11] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075c798 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075c7d8 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#12] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075c2b8 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075c2f8 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#13] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075bdd8 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075be18 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#14] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075b8f8 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075b938 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#15] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075b418 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075b458 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#16] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075af38 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075af78 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#17] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075aa58 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075aa98 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#18] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075a578 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075a5b8 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#19] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075a098 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075a0d8 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#20] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a0759bb8 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a0759bf8 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#21] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a07596d8 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a0759718 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#22] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a07591f8 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a0759238 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Oops: 0000 [#23] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a0758d18 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a0758d58 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
BUG: unable to handle page fault for address: fffffbfff4004000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 21ffee067 P4D 21ffee067 PUD 21ffed067 PMD 9b511067 PTE 0
Thread overran stack, or stack corrupted
Oops: 0000 [#24] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a0758838 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a0758878 R08: ffff8880a073c600 R09: 0000000000000000
R10: ffffed1015d06c6f R11: ffff8880a073c600 R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffff01 R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
------------[ cut here ]------------
==================================================================
BUG: KASAN: use-after-free in vsnprintf+0xe9e/0x19a0 lib/vsprintf.c:2536
Read of size 8 at addr ffff8880a0757798 by task kworker/0:2/2952
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
Call Trace:
------------[ cut here ]------------
kernel BUG at mm/slab.c:4169!
invalid opcode: 0000 [#25] PREEMPT SMP KASAN
CPU: 0 PID: 2952 Comm: kworker/0:2 Not tainted 5.2.0-rc5-next-20190617 #16
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: events bpf_prog_free_deferred
RIP: 0010:__check_heap_object+0xa5/0xb3 mm/slab.c:4169
Code: 2b 48 c7 c7 4d 46 83 88 e8 88 bd 07 00 5d c3 41 8b 91 3c 01 00 00 48
29 c7 48 39 d7 77 bd 48 01 d0 48 29 c8 4c 39 c0 72 b2 c3 <0f> 0b 48 c7 c7
4d 46 83 88 e8 9c c2 07 00 4c 8d 45 c4 89 d9 48 c7
RSP: 0018:ffff8880a0756f00 EFLAGS: 00010046
RAX: 000000000000000a RBX: 0000000000000001 RCX: 0000000000000008
RDX: ffff8880a0756000 RSI: 0000000000000000 RDI: ffff8880a0756ff8
RBP: ffff8880a0756f50 R08: 0000000000000001 R09: ffff8880aa58f1c0
R10: 0000000000000412 R11: 0000000000000000 R12: ffff8880a0756ff8
R13: ffffea000281d580 R14: ffff8880a0756ff9 R15: 0000000000000001
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
Modules linked in:
---[ end trace 744eff192875d43e ]---
RIP: 0010:bpf_get_prog_addr_region kernel/bpf/core.c:537 [inline]
RIP: 0010:bpf_tree_comp kernel/bpf/core.c:600 [inline]
RIP: 0010:__lt_find include/linux/rbtree_latch.h:115 [inline]
RIP: 0010:latch_tree_find include/linux/rbtree_latch.h:208 [inline]
RIP: 0010:bpf_prog_kallsyms_find kernel/bpf/core.c:674 [inline]
RIP: 0010:bpf_prog_kallsyms_find+0x1a0/0x2c0 kernel/bpf/core.c:667
Code: 75 07 e8 53 f2 f4 ff 0f 0b e8 4c f2 f4 ff 48 89 de 4c 89 f7 e8 61 f3
f4 ff 49 39 de 72 71 e8 37 f2 f4 ff 48 89 d8 48 c1 e8 03 <42> 0f b6 04 28
84 c0 74 08 3c 03 0f 8e e6 00 00 00 8b 33 4c 89 f7
RSP: 0018:ffff8880a075f850 EFLAGS: 00010806
RAX: 1ffffffff4004000 RBX: ffffffffa0020000 RCX: ffffffff817c0d0f
RDX: 0000000000000000 RSI: ffffffff817c0d19 RDI: 0000000000000006
RBP: ffff8880a075f890 R08: ffff8880a073c600 R09: ffffed1015d06c70
R10: ffffed1015d06c6f R11: ffff8880ae83637b R12: ffff88809a4f8578
R13: dffffc0000000000 R14: ffffffffffffffff R15: ffff88809a4f8578
FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff4004000 CR3: 00000000994d7000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
^ permalink raw reply
* Re: [PATCH] bpf: optimize constant blinding
From: Jiong Wang @ 2019-06-17 19:59 UTC (permalink / raw)
To: Edward Cree
Cc: Jiong Wang, Alexei Starovoitov, Naveen N. Rao, Daniel Borkmann,
bpf, Network Development, Michael Ellerman, Jakub Kicinski
In-Reply-To: <41dfe080-be03-3344-d279-e638a5a6168d@solarflare.com>
Edward Cree writes:
> On 14/06/2019 16:13, Jiong Wang wrote:
>> Just an update and keep people posted.
>>
>> Working on linked list based approach, the implementation looks like the
>> following, mostly a combine of discussions happened and Naveen's patch,
>> please feel free to comment.
>>
>> - Use the reserved opcode 0xf0 with BPF_ALU as new pseudo insn code
>> BPF_LIST_INSN. (0xf0 is also used with BPF_JMP class for tail call).
>>
>> - Introduce patch pool into bpf_prog->aux to keep all patched insns.
> It's not clear to me what the point of the patch pool is, rather than just
> doing the patch straight away.
I used pool because I was thinking insn to be patched could be high
percentage, so doing lots of alloc call is going to be less efficient? so
allocate a big pool, and each time when creating new patch node, allocate
it from the pool directly. Node is addressed using pool_base + offset, each
node only need to keep offset.
> Idea is that when prog is half-patched,
> insn idxs / jump offsets / etc. all refer to the original locations, only
> some of those might now be a list rather than a single insn. Concretely:
>
> struct bpf_insn_list { bpf_insn insn; struct list_head list; }
> orig prog: array bpf_insn[3] = {cond jump +1, insn_foo, exit};
> start of day verifier converts this into array bpf_insn_list[3],
> each with new.insn = orig.insn; INIT_LIST_HEAD(new.list)
>
> verifier decides to patch insn_foo into {insn_bar, insn_baz}.
> so we allocate bpf_insn_list *x;
> insn_foo.insn = insn_bar;
> x->insn = insn_baz;
> list_add_tail(&x->list, &insn_foo.list);
>
> the cond jump +1 is _not_ changed at this point, because it counts
> bpf_insn_lists and not insns.
>
> Then at end of day to linearise we just have int new_idx[3];
> populate it by iterating over the array of bpf_insn_list and adding on
> the list length each time (so we get {0, 1, 3})
> then allocate output prog of the total length (here 4, calculated by
> that same pass as effectively off-the-end entry of new_idx)
> then iterate again to write out the output prog, when we see that 'cond
> jump +1' in old_idx 0 we see that (new_idx[2] - new_idx[0] - 1) = 2, so
> it becomes 'cond jump +2'.
>
>
> This seems to me like it'd be easier to work with than making the whole
> program one big linked list (where you have to separately keep track of
> what each insn's idx was before patching). But I haven't tried to code
> it yet, so anything could happen ;-) It does rely on the assumption
> that only original insns (or the first insn of a list they get patched
> with) will ever be jump targets or otherwise need their insn_idx taken.
>
> -Ed
^ permalink raw reply
* [PATCH] e1000e: Make watchdog use delayed work
From: Detlev Casanova @ 2019-06-17 19:54 UTC (permalink / raw)
To: Jeff Kirsher, David S. Miller, intel-wired-lan, netdev,
linux-kernel
Cc: Detlev Casanova
Use delayed work instead of timers to run the watchdog of the e1000e
driver.
Simplify the code with one less middle function.
Signed-off-by: Detlev Casanova <detlev.casanova@gmail.com>
---
drivers/net/ethernet/intel/e1000e/e1000.h | 3 +-
drivers/net/ethernet/intel/e1000e/netdev.c | 52 +++++++++++-----------
2 files changed, 28 insertions(+), 27 deletions(-)
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index be13227f1697..942ab74030ca 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -186,12 +186,11 @@ struct e1000_phy_regs {
/* board specific private data structure */
struct e1000_adapter {
- struct timer_list watchdog_timer;
struct timer_list phy_info_timer;
struct timer_list blink_timer;
struct work_struct reset_task;
- struct work_struct watchdog_task;
+ struct delayed_work watchdog_task;
const struct e1000_info *ei;
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 0e09bede42a2..f62434aa24ad 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -39,6 +39,8 @@ static int debug = -1;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+static struct workqueue_struct *e1000_workqueue;
+
static const struct e1000_info *e1000_info_tbl[] = {
[board_82571] = &e1000_82571_info,
[board_82572] = &e1000_82572_info,
@@ -1780,7 +1782,7 @@ static irqreturn_t e1000_intr_msi(int __always_unused irq, void *data)
}
/* guard against interrupt when we're going down */
if (!test_bit(__E1000_DOWN, &adapter->state))
- mod_timer(&adapter->watchdog_timer, jiffies + 1);
+ queue_delayed_work(e1000_workqueue, &adapter->watchdog_task, 1);
}
/* Reset on uncorrectable ECC error */
@@ -1860,7 +1862,7 @@ static irqreturn_t e1000_intr(int __always_unused irq, void *data)
}
/* guard against interrupt when we're going down */
if (!test_bit(__E1000_DOWN, &adapter->state))
- mod_timer(&adapter->watchdog_timer, jiffies + 1);
+ queue_delayed_work(e1000_workqueue, &adapter->watchdog_task, 1);
}
/* Reset on uncorrectable ECC error */
@@ -1905,7 +1907,7 @@ static irqreturn_t e1000_msix_other(int __always_unused irq, void *data)
hw->mac.get_link_status = true;
/* guard against interrupt when we're going down */
if (!test_bit(__E1000_DOWN, &adapter->state))
- mod_timer(&adapter->watchdog_timer, jiffies + 1);
+ queue_delayed_work(e1000_workqueue, &adapter->watchdog_task, 0);
}
if (!test_bit(__E1000_DOWN, &adapter->state))
@@ -4278,7 +4280,6 @@ void e1000e_down(struct e1000_adapter *adapter, bool reset)
napi_synchronize(&adapter->napi);
- del_timer_sync(&adapter->watchdog_timer);
del_timer_sync(&adapter->phy_info_timer);
spin_lock(&adapter->stats64_lock);
@@ -5150,25 +5151,11 @@ static void e1000e_check_82574_phy_workaround(struct e1000_adapter *adapter)
}
}
-/**
- * e1000_watchdog - Timer Call-back
- * @data: pointer to adapter cast into an unsigned long
- **/
-static void e1000_watchdog(struct timer_list *t)
-{
- struct e1000_adapter *adapter = from_timer(adapter, t, watchdog_timer);
-
- /* Do the rest outside of interrupt context */
- schedule_work(&adapter->watchdog_task);
-
- /* TODO: make this use queue_delayed_work() */
-}
-
static void e1000_watchdog_task(struct work_struct *work)
{
struct e1000_adapter *adapter = container_of(work,
struct e1000_adapter,
- watchdog_task);
+ watchdog_task.work);
struct net_device *netdev = adapter->netdev;
struct e1000_mac_info *mac = &adapter->hw.mac;
struct e1000_phy_info *phy = &adapter->hw.phy;
@@ -5395,8 +5382,8 @@ static void e1000_watchdog_task(struct work_struct *work)
/* Reset the timer */
if (!test_bit(__E1000_DOWN, &adapter->state))
- mod_timer(&adapter->watchdog_timer,
- round_jiffies(jiffies + 2 * HZ));
+ queue_delayed_work(e1000_workqueue, &adapter->watchdog_task,
+ round_jiffies(2 * HZ));
}
#define E1000_TX_FLAGS_CSUM 0x00000001
@@ -7251,11 +7238,21 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_eeprom;
}
- timer_setup(&adapter->watchdog_timer, e1000_watchdog, 0);
+ e1000_workqueue = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0,
+ e1000e_driver_name);
+
+ if (!e1000_workqueue)
+ {
+ err = -ENOMEM;
+ goto err_workqueue;
+ }
+
+ INIT_DELAYED_WORK(&adapter->watchdog_task, e1000_watchdog_task);
+ queue_delayed_work(e1000_workqueue, &adapter->watchdog_task, 0);
+
timer_setup(&adapter->phy_info_timer, e1000_update_phy_info, 0);
INIT_WORK(&adapter->reset_task, e1000_reset_task);
- INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task);
INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround);
INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task);
INIT_WORK(&adapter->print_hang_task, e1000_print_hw_hang);
@@ -7349,6 +7346,9 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
err_register:
+ flush_workqueue(e1000_workqueue);
+ destroy_workqueue(e1000_workqueue);
+err_workqueue:
if (!(adapter->flags & FLAG_HAS_AMT))
e1000e_release_hw_control(adapter);
err_eeprom:
@@ -7395,15 +7395,17 @@ static void e1000_remove(struct pci_dev *pdev)
*/
if (!down)
set_bit(__E1000_DOWN, &adapter->state);
- del_timer_sync(&adapter->watchdog_timer);
del_timer_sync(&adapter->phy_info_timer);
cancel_work_sync(&adapter->reset_task);
- cancel_work_sync(&adapter->watchdog_task);
cancel_work_sync(&adapter->downshift_task);
cancel_work_sync(&adapter->update_phy_task);
cancel_work_sync(&adapter->print_hang_task);
+ cancel_delayed_work(&adapter->watchdog_task);
+ flush_workqueue(e1000_workqueue);
+ destroy_workqueue(e1000_workqueue);
+
if (adapter->flags & FLAG_HAS_HW_TIMESTAMP) {
cancel_work_sync(&adapter->tx_hwtstamp_work);
if (adapter->tx_hwtstamp_skb) {
--
2.22.0
^ permalink raw reply related
* Re: [PATCH] bpf: optimize constant blinding
From: Edward Cree @ 2019-06-17 19:47 UTC (permalink / raw)
To: Jiong Wang, Alexei Starovoitov
Cc: Naveen N. Rao, Daniel Borkmann, bpf, Network Development,
Michael Ellerman, Jakub Kicinski
In-Reply-To: <87ef3w5hew.fsf@netronome.com>
On 14/06/2019 16:13, Jiong Wang wrote:
> Just an update and keep people posted.
>
> Working on linked list based approach, the implementation looks like the
> following, mostly a combine of discussions happened and Naveen's patch,
> please feel free to comment.
>
> - Use the reserved opcode 0xf0 with BPF_ALU as new pseudo insn code
> BPF_LIST_INSN. (0xf0 is also used with BPF_JMP class for tail call).
>
> - Introduce patch pool into bpf_prog->aux to keep all patched insns.
It's not clear to me what the point of the patch pool is, rather than just
doing the patch straight away. Idea is that when prog is half-patched,
insn idxs / jump offsets / etc. all refer to the original locations, only
some of those might now be a list rather than a single insn. Concretely:
struct bpf_insn_list { bpf_insn insn; struct list_head list; }
orig prog: array bpf_insn[3] = {cond jump +1, insn_foo, exit};
start of day verifier converts this into array bpf_insn_list[3],
each with new.insn = orig.insn; INIT_LIST_HEAD(new.list)
verifier decides to patch insn_foo into {insn_bar, insn_baz}.
so we allocate bpf_insn_list *x;
insn_foo.insn = insn_bar;
x->insn = insn_baz;
list_add_tail(&x->list, &insn_foo.list);
the cond jump +1 is _not_ changed at this point, because it counts
bpf_insn_lists and not insns.
Then at end of day to linearise we just have int new_idx[3];
populate it by iterating over the array of bpf_insn_list and adding on
the list length each time (so we get {0, 1, 3})
then allocate output prog of the total length (here 4, calculated by
that same pass as effectively off-the-end entry of new_idx)
then iterate again to write out the output prog, when we see that 'cond
jump +1' in old_idx 0 we see that (new_idx[2] - new_idx[0] - 1) = 2, so
it becomes 'cond jump +2'.
This seems to me like it'd be easier to work with than making the whole
program one big linked list (where you have to separately keep track of
what each insn's idx was before patching). But I haven't tried to code
it yet, so anything could happen ;-) It does rely on the assumption
that only original insns (or the first insn of a list they get patched
with) will ever be jump targets or otherwise need their insn_idx taken.
-Ed
^ permalink raw reply
* Re: [PATCH v2 bpf-next 03/11] libbpf: streamline ELF parsing error-handling
From: Song Liu @ 2019-06-17 19:46 UTC (permalink / raw)
To: Andrii Nakryiko
Cc: Andrii Nakryiko, Alexei Starovoitov, daniel@iogearbox.net,
netdev@vger.kernel.org, bpf@vger.kernel.org, Kernel Team
In-Reply-To: <20190617192700.2313445-4-andriin@fb.com>
> On Jun 17, 2019, at 12:26 PM, Andrii Nakryiko <andriin@fb.com> wrote:
>
> Simplify ELF parsing logic by exiting early, as there is no common clean
> up path to execute. That makes it unnecessary to track when err was set
> and when it was cleared. It also reduces nesting in some places.
>
> Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Acked-by: Song Liu <songliubraving@fb.com>
<snip>
^ permalink raw reply
* Re: [PATCH v2 bpf-next 07/11] libbpf: allow specifying map definitions using BTF
From: Song Liu @ 2019-06-17 19:43 UTC (permalink / raw)
To: Andrii Nakryiko
Cc: Andrii Nakryiko, Alexei Starovoitov, daniel@iogearbox.net,
netdev@vger.kernel.org, bpf@vger.kernel.org, Kernel Team
In-Reply-To: <20190617192700.2313445-8-andriin@fb.com>
> On Jun 17, 2019, at 12:26 PM, Andrii Nakryiko <andriin@fb.com> wrote:
>
> This patch adds support for a new way to define BPF maps. It relies on
> BTF to describe mandatory and optional attributes of a map, as well as
> captures type information of key and value naturally. This eliminates
> the need for BPF_ANNOTATE_KV_PAIR hack and ensures key/value sizes are
> always in sync with the key/value type.
>
> Relying on BTF, this approach allows for both forward and backward
> compatibility w.r.t. extending supported map definition features. By
> default, any unrecognized attributes are treated as an error, but it's
> possible relax this using MAPS_RELAX_COMPAT flag. New attributes, added
> in the future will need to be optional.
>
> The outline of the new map definition (short, BTF-defined maps) is as follows:
> 1. All the maps should be defined in .maps ELF section. It's possible to
> have both "legacy" map definitions in `maps` sections and BTF-defined
> maps in .maps sections. Everything will still work transparently.
> 2. The map declaration and initialization is done through
> a global/static variable of a struct type with few mandatory and
> extra optional fields:
> - type field is mandatory and specified type of BPF map;
> - key/value fields are mandatory and capture key/value type/size information;
> - max_entries attribute is optional; if max_entries is not specified or
> initialized, it has to be provided in runtime through libbpf API
> before loading bpf_object;
> - map_flags is optional and if not defined, will be assumed to be 0.
> 3. Key/value fields should be **a pointer** to a type describing
> key/value. The pointee type is assumed (and will be recorded as such
> and used for size determination) to be a type describing key/value of
> the map. This is done to save excessive amounts of space allocated in
> corresponding ELF sections for key/value of big size.
> 4. As some maps disallow having BTF type ID associated with key/value,
> it's possible to specify key/value size explicitly without
> associating BTF type ID with it. Use key_size and value_size fields
> to do that (see example below).
>
> Here's an example of simple ARRAY map defintion:
>
> struct my_value { int x, y, z; };
>
> struct {
> int type;
> int max_entries;
> int *key;
> struct my_value *value;
> } btf_map SEC(".maps") = {
> .type = BPF_MAP_TYPE_ARRAY,
> .max_entries = 16,
> };
>
> This will define BPF ARRAY map 'btf_map' with 16 elements. The key will
> be of type int and thus key size will be 4 bytes. The value is struct
> my_value of size 12 bytes. This map can be used from C code exactly the
> same as with existing maps defined through struct bpf_map_def.
>
> Here's an example of STACKMAP definition (which currently disallows BTF type
> IDs for key/value):
>
> struct {
> __u32 type;
> __u32 max_entries;
> __u32 map_flags;
> __u32 key_size;
> __u32 value_size;
> } stackmap SEC(".maps") = {
> .type = BPF_MAP_TYPE_STACK_TRACE,
> .max_entries = 128,
> .map_flags = BPF_F_STACK_BUILD_ID,
> .key_size = sizeof(__u32),
> .value_size = PERF_MAX_STACK_DEPTH * sizeof(struct bpf_stack_build_id),
> };
>
> This approach is naturally extended to support map-in-map, by making a value
> field to be another struct that describes inner map. This feature is not
> implemented yet. It's also possible to incrementally add features like pinning
> with full backwards and forward compatibility. Support for static
> initialization of BPF_MAP_TYPE_PROG_ARRAY using pointers to BPF programs
> is also on the roadmap.
>
> Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Acked-by: Song Liu <songliubraving@fb.com>
> ---
> tools/lib/bpf/btf.h | 1 +
> tools/lib/bpf/libbpf.c | 353 +++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 345 insertions(+), 9 deletions(-)
>
> diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
> index ba4ffa831aa4..88a52ae56fc6 100644
> --- a/tools/lib/bpf/btf.h
> +++ b/tools/lib/bpf/btf.h
> @@ -17,6 +17,7 @@ extern "C" {
>
> #define BTF_ELF_SEC ".BTF"
> #define BTF_EXT_ELF_SEC ".BTF.ext"
> +#define MAPS_ELF_SEC ".maps"
>
> struct btf;
> struct btf_ext;
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index da942ab2f06a..585e3a2f1eb4 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -262,6 +262,7 @@ struct bpf_object {
> } *reloc;
> int nr_reloc;
> int maps_shndx;
> + int btf_maps_shndx;
> int text_shndx;
> int data_shndx;
> int rodata_shndx;
> @@ -514,6 +515,7 @@ static struct bpf_object *bpf_object__new(const char *path,
> obj->efile.obj_buf = obj_buf;
> obj->efile.obj_buf_sz = obj_buf_sz;
> obj->efile.maps_shndx = -1;
> + obj->efile.btf_maps_shndx = -1;
> obj->efile.data_shndx = -1;
> obj->efile.rodata_shndx = -1;
> obj->efile.bss_shndx = -1;
> @@ -1007,6 +1009,312 @@ static int bpf_object__init_user_maps(struct bpf_object *obj, bool strict)
> return 0;
> }
>
> +static const struct btf_type *skip_mods_and_typedefs(const struct btf *btf,
> + __u32 id)
> +{
> + const struct btf_type *t = btf__type_by_id(btf, id);
> +
> + while (true) {
> + switch (BTF_INFO_KIND(t->info)) {
> + case BTF_KIND_VOLATILE:
> + case BTF_KIND_CONST:
> + case BTF_KIND_RESTRICT:
> + case BTF_KIND_TYPEDEF:
> + t = btf__type_by_id(btf, t->type);
> + break;
> + default:
> + return t;
> + }
> + }
> +}
> +
> +static bool get_map_field_int(const char *map_name,
> + const struct btf *btf,
> + const struct btf_type *def,
> + const struct btf_member *m,
> + const void *data, __u32 *res) {
> + const struct btf_type *t = skip_mods_and_typedefs(btf, m->type);
> + const char *name = btf__name_by_offset(btf, m->name_off);
> + __u32 int_info = *(const __u32 *)(const void *)(t + 1);
> +
> + if (BTF_INFO_KIND(t->info) != BTF_KIND_INT) {
> + pr_warning("map '%s': attr '%s': expected INT, got %u.\n",
> + map_name, name, BTF_INFO_KIND(t->info));
> + return false;
> + }
> + if (t->size != 4 || BTF_INT_BITS(int_info) != 32 ||
> + BTF_INT_OFFSET(int_info)) {
> + pr_warning("map '%s': attr '%s': expected 32-bit non-bitfield integer, "
> + "got %u-byte (%d-bit) one with bit offset %d.\n",
> + map_name, name, t->size, BTF_INT_BITS(int_info),
> + BTF_INT_OFFSET(int_info));
> + return false;
> + }
> + if (BTF_INFO_KFLAG(def->info) && BTF_MEMBER_BITFIELD_SIZE(m->offset)) {
> + pr_warning("map '%s': attr '%s': bitfield is not supported.\n",
> + map_name, name);
> + return false;
> + }
> + if (m->offset % 32) {
> + pr_warning("map '%s': attr '%s': unaligned fields are not supported.\n",
> + map_name, name);
> + return false;
> + }
> +
> + *res = *(const __u32 *)(data + m->offset / 8);
> + return true;
> +}
> +
> +static int bpf_object__init_user_btf_map(struct bpf_object *obj,
> + const struct btf_type *sec,
> + int var_idx, int sec_idx,
> + const Elf_Data *data, bool strict)
> +{
> + const struct btf_type *var, *def, *t;
> + const struct btf_var_secinfo *vi;
> + const struct btf_var *var_extra;
> + const struct btf_member *m;
> + const void *def_data;
> + const char *map_name;
> + struct bpf_map *map;
> + int vlen, i;
> +
> + vi = (const struct btf_var_secinfo *)(const void *)(sec + 1) + var_idx;
> + var = btf__type_by_id(obj->btf, vi->type);
> + var_extra = (const void *)(var + 1);
> + map_name = btf__name_by_offset(obj->btf, var->name_off);
> + vlen = BTF_INFO_VLEN(var->info);
> +
> + if (map_name == NULL || map_name[0] == '\0') {
> + pr_warning("map #%d: empty name.\n", var_idx);
> + return -EINVAL;
> + }
> + if ((__u64)vi->offset + vi->size > data->d_size) {
> + pr_warning("map '%s' BTF data is corrupted.\n", map_name);
> + return -EINVAL;
> + }
> + if (BTF_INFO_KIND(var->info) != BTF_KIND_VAR) {
> + pr_warning("map '%s': unexpected var kind %u.\n",
> + map_name, BTF_INFO_KIND(var->info));
> + return -EINVAL;
> + }
> + if (var_extra->linkage != BTF_VAR_GLOBAL_ALLOCATED &&
> + var_extra->linkage != BTF_VAR_STATIC) {
> + pr_warning("map '%s': unsupported var linkage %u.\n",
> + map_name, var_extra->linkage);
> + return -EOPNOTSUPP;
> + }
> +
> + def = skip_mods_and_typedefs(obj->btf, var->type);
> + if (BTF_INFO_KIND(def->info) != BTF_KIND_STRUCT) {
> + pr_warning("map '%s': unexpected def kind %u.\n",
> + map_name, BTF_INFO_KIND(var->info));
> + return -EINVAL;
> + }
> + if (def->size > vi->size) {
> + pr_warning("map '%s': invalid def size.\n", map_name);
> + return -EINVAL;
> + }
> +
> + map = bpf_object__add_map(obj);
> + if (IS_ERR(map))
> + return PTR_ERR(map);
> + map->name = strdup(map_name);
> + if (!map->name) {
> + pr_warning("map '%s': failed to alloc map name.\n", map_name);
> + return -ENOMEM;
> + }
> + map->libbpf_type = LIBBPF_MAP_UNSPEC;
> + map->def.type = BPF_MAP_TYPE_UNSPEC;
> + map->sec_idx = sec_idx;
> + map->sec_offset = vi->offset;
> + pr_debug("map '%s': at sec_idx %d, offset %zu.\n",
> + map_name, map->sec_idx, map->sec_offset);
> +
> + def_data = data->d_buf + vi->offset;
> + vlen = BTF_INFO_VLEN(def->info);
> + m = (const void *)(def + 1);
> + for (i = 0; i < vlen; i++, m++) {
> + const char *name = btf__name_by_offset(obj->btf, m->name_off);
> +
> + if (!name) {
> + pr_warning("map '%s': invalid field #%d.\n",
> + map_name, i);
> + return -EINVAL;
> + }
> + if (strcmp(name, "type") == 0) {
> + if (!get_map_field_int(map_name, obj->btf, def, m,
> + def_data, &map->def.type))
> + return -EINVAL;
> + pr_debug("map '%s': found type = %u.\n",
> + map_name, map->def.type);
> + } else if (strcmp(name, "max_entries") == 0) {
> + if (!get_map_field_int(map_name, obj->btf, def, m,
> + def_data, &map->def.max_entries))
> + return -EINVAL;
> + pr_debug("map '%s': found max_entries = %u.\n",
> + map_name, map->def.max_entries);
> + } else if (strcmp(name, "map_flags") == 0) {
> + if (!get_map_field_int(map_name, obj->btf, def, m,
> + def_data, &map->def.map_flags))
> + return -EINVAL;
> + pr_debug("map '%s': found map_flags = %u.\n",
> + map_name, map->def.map_flags);
> + } else if (strcmp(name, "key_size") == 0) {
> + __u32 sz;
> +
> + if (!get_map_field_int(map_name, obj->btf, def, m,
> + def_data, &sz))
> + return -EINVAL;
> + pr_debug("map '%s': found key_size = %u.\n",
> + map_name, sz);
> + if (map->def.key_size && map->def.key_size != sz) {
> + pr_warning("map '%s': conflictling key size %u != %u.\n",
> + map_name, map->def.key_size, sz);
> + return -EINVAL;
> + }
> + map->def.key_size = sz;
> + } else if (strcmp(name, "key") == 0) {
> + __s64 sz;
> +
> + t = btf__type_by_id(obj->btf, m->type);
> + if (!t) {
> + pr_warning("map '%s': key type [%d] not found.\n",
> + map_name, m->type);
> + return -EINVAL;
> + }
> + if (BTF_INFO_KIND(t->info) != BTF_KIND_PTR) {
> + pr_warning("map '%s': key spec is not PTR: %u.\n",
> + map_name, BTF_INFO_KIND(t->info));
> + return -EINVAL;
> + }
> + sz = btf__resolve_size(obj->btf, t->type);
> + if (sz < 0) {
> + pr_warning("map '%s': can't determine key size for type [%u]: %lld.\n",
> + map_name, t->type, sz);
> + return sz;
> + }
> + pr_debug("map '%s': found key [%u], sz = %lld.\n",
> + map_name, t->type, sz);
> + if (map->def.key_size && map->def.key_size != sz) {
> + pr_warning("map '%s': conflictling key size %u != %lld.\n",
> + map_name, map->def.key_size, sz);
> + return -EINVAL;
> + }
> + map->def.key_size = sz;
> + map->btf_key_type_id = t->type;
> + } else if (strcmp(name, "value_size") == 0) {
> + __u32 sz;
> +
> + if (!get_map_field_int(map_name, obj->btf, def, m,
> + def_data, &sz))
> + return -EINVAL;
> + pr_debug("map '%s': found value_size = %u.\n",
> + map_name, sz);
> + if (map->def.value_size && map->def.value_size != sz) {
> + pr_warning("map '%s': conflictling value size %u != %u.\n",
> + map_name, map->def.value_size, sz);
> + return -EINVAL;
> + }
> + map->def.value_size = sz;
> + } else if (strcmp(name, "value") == 0) {
> + __s64 sz;
> +
> + t = btf__type_by_id(obj->btf, m->type);
> + if (!t) {
> + pr_warning("map '%s': value type [%d] not found.\n",
> + map_name, m->type);
> + return -EINVAL;
> + }
> + if (BTF_INFO_KIND(t->info) != BTF_KIND_PTR) {
> + pr_warning("map '%s': value spec is not PTR: %u.\n",
> + map_name, BTF_INFO_KIND(t->info));
> + return -EINVAL;
> + }
> + sz = btf__resolve_size(obj->btf, t->type);
> + if (sz < 0) {
> + pr_warning("map '%s': can't determine value size for type [%u]: %lld.\n",
> + map_name, t->type, sz);
> + return sz;
> + }
> + pr_debug("map '%s': found value [%u], sz = %lld.\n",
> + map_name, t->type, sz);
> + if (map->def.value_size && map->def.value_size != sz) {
> + pr_warning("map '%s': conflictling value size %u != %lld.\n",
> + map_name, map->def.value_size, sz);
> + return -EINVAL;
> + }
> + map->def.value_size = sz;
> + map->btf_value_type_id = t->type;
> + } else {
> + if (strict) {
> + pr_warning("map '%s': unknown field '%s'.\n",
> + map_name, name);
> + return -ENOTSUP;
> + }
> + pr_debug("map '%s': ignoring unknown field '%s'.\n",
> + map_name, name);
> + }
> + }
> +
> + if (map->def.type == BPF_MAP_TYPE_UNSPEC) {
> + pr_warning("map '%s': map type isn't specified.\n", map_name);
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int bpf_object__init_user_btf_maps(struct bpf_object *obj, bool strict)
> +{
> + const struct btf_type *sec = NULL;
> + int nr_types, i, vlen, err;
> + const struct btf_type *t;
> + const char *name;
> + Elf_Data *data;
> + Elf_Scn *scn;
> +
> + if (obj->efile.btf_maps_shndx < 0)
> + return 0;
> +
> + scn = elf_getscn(obj->efile.elf, obj->efile.btf_maps_shndx);
> + if (scn)
> + data = elf_getdata(scn, NULL);
> + if (!scn || !data) {
> + pr_warning("failed to get Elf_Data from map section %d (%s)\n",
> + obj->efile.maps_shndx, MAPS_ELF_SEC);
> + return -EINVAL;
> + }
> +
> + nr_types = btf__get_nr_types(obj->btf);
> + for (i = 1; i <= nr_types; i++) {
> + t = btf__type_by_id(obj->btf, i);
> + if (BTF_INFO_KIND(t->info) != BTF_KIND_DATASEC)
> + continue;
> + name = btf__name_by_offset(obj->btf, t->name_off);
> + if (strcmp(name, MAPS_ELF_SEC) == 0) {
> + sec = t;
> + break;
> + }
> + }
> +
> + if (!sec) {
> + pr_warning("DATASEC '%s' not found.\n", MAPS_ELF_SEC);
> + return -ENOENT;
> + }
> +
> + vlen = BTF_INFO_VLEN(sec->info);
> + for (i = 0; i < vlen; i++) {
> + err = bpf_object__init_user_btf_map(obj, sec, i,
> + obj->efile.btf_maps_shndx,
> + data, strict);
> + if (err)
> + return err;
> + }
> +
> + return 0;
> +}
> +
> static int bpf_object__init_maps(struct bpf_object *obj, int flags)
> {
> bool strict = !(flags & MAPS_RELAX_COMPAT);
> @@ -1016,6 +1324,10 @@ static int bpf_object__init_maps(struct bpf_object *obj, int flags)
> if (err)
> return err;
>
> + err = bpf_object__init_user_btf_maps(obj, strict);
> + if (err)
> + return err;
> +
> err = bpf_object__init_global_data_maps(obj);
> if (err)
> return err;
> @@ -1113,10 +1425,16 @@ static void bpf_object__sanitize_btf_ext(struct bpf_object *obj)
> }
> }
>
> +static bool bpf_object__is_btf_mandatory(const struct bpf_object *obj)
> +{
> + return obj->efile.btf_maps_shndx >= 0;
> +}
> +
> static int bpf_object__init_btf(struct bpf_object *obj,
> Elf_Data *btf_data,
> Elf_Data *btf_ext_data)
> {
> + bool btf_required = bpf_object__is_btf_mandatory(obj);
> int err = 0;
>
> if (btf_data) {
> @@ -1150,10 +1468,18 @@ static int bpf_object__init_btf(struct bpf_object *obj,
> }
> out:
> if (err || IS_ERR(obj->btf)) {
> + if (btf_required)
> + err = err ? : PTR_ERR(obj->btf);
> + else
> + err = 0;
> if (!IS_ERR_OR_NULL(obj->btf))
> btf__free(obj->btf);
> obj->btf = NULL;
> }
> + if (btf_required && !obj->btf) {
> + pr_warning("BTF is required, but is missing or corrupted.\n");
> + return err == 0 ? -ENOENT : err;
> + }
> return 0;
> }
>
> @@ -1173,6 +1499,8 @@ static int bpf_object__sanitize_and_load_btf(struct bpf_object *obj)
> BTF_ELF_SEC, err);
> btf__free(obj->btf);
> obj->btf = NULL;
> + if (bpf_object__is_btf_mandatory(obj))
> + return err;
> }
> return 0;
> }
> @@ -1236,6 +1564,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
> return err;
> } else if (strcmp(name, "maps") == 0) {
> obj->efile.maps_shndx = idx;
> + } else if (strcmp(name, MAPS_ELF_SEC) == 0) {
> + obj->efile.btf_maps_shndx = idx;
> } else if (strcmp(name, BTF_ELF_SEC) == 0) {
> btf_data = data;
> } else if (strcmp(name, BTF_EXT_ELF_SEC) == 0) {
> @@ -1355,7 +1685,8 @@ static bool bpf_object__shndx_is_data(const struct bpf_object *obj,
> static bool bpf_object__shndx_is_maps(const struct bpf_object *obj,
> int shndx)
> {
> - return shndx == obj->efile.maps_shndx;
> + return shndx == obj->efile.maps_shndx ||
> + shndx == obj->efile.btf_maps_shndx;
> }
>
> static bool bpf_object__relo_in_known_section(const struct bpf_object *obj,
> @@ -1399,14 +1730,14 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr,
> prog->nr_reloc = nrels;
>
> for (i = 0; i < nrels; i++) {
> - GElf_Sym sym;
> - GElf_Rel rel;
> - unsigned int insn_idx;
> - unsigned int shdr_idx;
> struct bpf_insn *insns = prog->insns;
> enum libbpf_map_type type;
> + unsigned int insn_idx;
> + unsigned int shdr_idx;
> const char *name;
> size_t map_idx;
> + GElf_Sym sym;
> + GElf_Rel rel;
>
> if (!gelf_getrel(data, i, &rel)) {
> pr_warning("relocation: failed to get %d reloc\n", i);
> @@ -1500,14 +1831,18 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr,
> return 0;
> }
>
> -static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf)
> +static int bpf_map_find_btf_info(struct bpf_object *obj, struct bpf_map *map)
> {
> struct bpf_map_def *def = &map->def;
> __u32 key_type_id = 0, value_type_id = 0;
> int ret;
>
> + /* if it's BTF-defined map, we don't need to search for type IDs */
> + if (map->sec_idx == obj->efile.btf_maps_shndx)
> + return 0;
> +
> if (!bpf_map__is_internal(map)) {
> - ret = btf__get_map_kv_tids(btf, map->name, def->key_size,
> + ret = btf__get_map_kv_tids(obj->btf, map->name, def->key_size,
> def->value_size, &key_type_id,
> &value_type_id);
> } else {
> @@ -1515,7 +1850,7 @@ static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf)
> * LLVM annotates global data differently in BTF, that is,
> * only as '.data', '.bss' or '.rodata'.
> */
> - ret = btf__find_by_name(btf,
> + ret = btf__find_by_name(obj->btf,
> libbpf_type_to_btf_name[map->libbpf_type]);
> }
> if (ret < 0)
> @@ -1805,7 +2140,7 @@ bpf_object__create_maps(struct bpf_object *obj)
> map->inner_map_fd >= 0)
> create_attr.inner_map_fd = map->inner_map_fd;
>
> - if (obj->btf && !bpf_map_find_btf_info(map, obj->btf)) {
> + if (obj->btf && !bpf_map_find_btf_info(obj, map)) {
> create_attr.btf_fd = btf__fd(obj->btf);
> create_attr.btf_key_type_id = map->btf_key_type_id;
> create_attr.btf_value_type_id = map->btf_value_type_id;
> --
> 2.17.1
>
^ permalink raw reply
* Re: [PATCH v2 bpf-next 02/11] libbpf: extract BTF loading logic
From: Song Liu @ 2019-06-17 19:40 UTC (permalink / raw)
To: Andrii Nakryiko
Cc: Andrii Nakryiko, Alexei Starovoitov, daniel@iogearbox.net,
netdev@vger.kernel.org, bpf@vger.kernel.org, Kernel Team
In-Reply-To: <20190617192700.2313445-3-andriin@fb.com>
> On Jun 17, 2019, at 12:26 PM, Andrii Nakryiko <andriin@fb.com> wrote:
>
> As a preparetion fro adding BTF-based BPF map loading, extract .BTF and
> .BTF.ext loading logic.
>
> Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Acked-by: Song Liu <songliubraving@fb.com>
> ---
> tools/lib/bpf/libbpf.c | 93 +++++++++++++++++++++++++-----------------
> 1 file changed, 55 insertions(+), 38 deletions(-)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index e725fa86b189..49d3a808e754 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -1078,6 +1078,58 @@ static void bpf_object__sanitize_btf_ext(struct bpf_object *obj)
> }
> }
>
> +static int bpf_object__load_btf(struct bpf_object *obj,
> + Elf_Data *btf_data,
> + Elf_Data *btf_ext_data)
> +{
> + int err = 0;
> +
> + if (btf_data) {
> + obj->btf = btf__new(btf_data->d_buf, btf_data->d_size);
> + if (IS_ERR(obj->btf)) {
> + pr_warning("Error loading ELF section %s: %d.\n",
> + BTF_ELF_SEC, err);
> + goto out;
> + }
> + err = btf__finalize_data(obj, obj->btf);
> + if (err) {
> + pr_warning("Error finalizing %s: %d.\n",
> + BTF_ELF_SEC, err);
> + goto out;
> + }
> + bpf_object__sanitize_btf(obj);
> + err = btf__load(obj->btf);
> + if (err) {
> + pr_warning("Error loading %s into kernel: %d.\n",
> + BTF_ELF_SEC, err);
> + goto out;
> + }
> + }
> + if (btf_ext_data) {
> + if (!obj->btf) {
> + pr_debug("Ignore ELF section %s because its depending ELF section %s is not found.\n",
> + BTF_EXT_ELF_SEC, BTF_ELF_SEC);
> + goto out;
> + }
> + obj->btf_ext = btf_ext__new(btf_ext_data->d_buf,
> + btf_ext_data->d_size);
> + if (IS_ERR(obj->btf_ext)) {
> + pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
> + BTF_EXT_ELF_SEC, PTR_ERR(obj->btf_ext));
> + obj->btf_ext = NULL;
> + goto out;
> + }
> + bpf_object__sanitize_btf_ext(obj);
> + }
> +out:
> + if (err || IS_ERR(obj->btf)) {
> + if (!IS_ERR_OR_NULL(obj->btf))
> + btf__free(obj->btf);
> + obj->btf = NULL;
> + }
> + return 0;
> +}
> +
> static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
> {
> Elf *elf = obj->efile.elf;
> @@ -1212,44 +1264,9 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
> pr_warning("Corrupted ELF file: index of strtab invalid\n");
> return -LIBBPF_ERRNO__FORMAT;
> }
> - if (btf_data) {
> - obj->btf = btf__new(btf_data->d_buf, btf_data->d_size);
> - if (IS_ERR(obj->btf)) {
> - pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
> - BTF_ELF_SEC, PTR_ERR(obj->btf));
> - obj->btf = NULL;
> - } else {
> - err = btf__finalize_data(obj, obj->btf);
> - if (!err) {
> - bpf_object__sanitize_btf(obj);
> - err = btf__load(obj->btf);
> - }
> - if (err) {
> - pr_warning("Error finalizing and loading %s into kernel: %d. Ignored and continue.\n",
> - BTF_ELF_SEC, err);
> - btf__free(obj->btf);
> - obj->btf = NULL;
> - err = 0;
> - }
> - }
> - }
> - if (btf_ext_data) {
> - if (!obj->btf) {
> - pr_debug("Ignore ELF section %s because its depending ELF section %s is not found.\n",
> - BTF_EXT_ELF_SEC, BTF_ELF_SEC);
> - } else {
> - obj->btf_ext = btf_ext__new(btf_ext_data->d_buf,
> - btf_ext_data->d_size);
> - if (IS_ERR(obj->btf_ext)) {
> - pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
> - BTF_EXT_ELF_SEC,
> - PTR_ERR(obj->btf_ext));
> - obj->btf_ext = NULL;
> - } else {
> - bpf_object__sanitize_btf_ext(obj);
> - }
> - }
> - }
> + err = bpf_object__load_btf(obj, btf_data, btf_ext_data);
> + if (err)
> + return err;
> if (bpf_object__has_maps(obj)) {
> err = bpf_object__init_maps(obj, flags);
> if (err)
> --
> 2.17.1
>
^ permalink raw reply
* Re: [PATCH v2 bpf-next 04/11] libbpf: refactor map initialization
From: Song Liu @ 2019-06-17 19:39 UTC (permalink / raw)
To: Andrii Nakryiko
Cc: Andrii Nakryiko, Alexei Starovoitov, daniel@iogearbox.net,
netdev@vger.kernel.org, bpf@vger.kernel.org, Kernel Team
In-Reply-To: <20190617192700.2313445-5-andriin@fb.com>
> On Jun 17, 2019, at 12:26 PM, Andrii Nakryiko <andriin@fb.com> wrote:
>
> User and global data maps initialization has gotten pretty complicated
> and unnecessarily convoluted. This patch splits out the logic for global
> data map and user-defined map initialization. It also removes the
> restriction of pre-calculating how many maps will be initialized,
> instead allowing to keep adding new maps as they are discovered, which
> will be used later for BTF-defined map definitions.
>
> Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Acked-by: Song Liu <songliubraving@fb.com>
> ---
> tools/lib/bpf/libbpf.c | 247 ++++++++++++++++++++++-------------------
> 1 file changed, 133 insertions(+), 114 deletions(-)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 7ee44d8877c5..88609dca4f7d 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -234,6 +234,7 @@ struct bpf_object {
> size_t nr_programs;
> struct bpf_map *maps;
> size_t nr_maps;
> + size_t maps_cap;
> struct bpf_secdata sections;
>
> bool loaded;
> @@ -763,21 +764,51 @@ int bpf_object__variable_offset(const struct bpf_object *obj, const char *name,
> return -ENOENT;
> }
>
> -static bool bpf_object__has_maps(const struct bpf_object *obj)
> +static struct bpf_map *bpf_object__add_map(struct bpf_object *obj)
> {
> - return obj->efile.maps_shndx >= 0 ||
> - obj->efile.data_shndx >= 0 ||
> - obj->efile.rodata_shndx >= 0 ||
> - obj->efile.bss_shndx >= 0;
> + struct bpf_map *new_maps;
> + size_t new_cap;
> + int i;
> +
> + if (obj->nr_maps < obj->maps_cap)
> + return &obj->maps[obj->nr_maps++];
> +
> + new_cap = max(4ul, obj->maps_cap * 3 / 2);
> + new_maps = realloc(obj->maps, new_cap * sizeof(*obj->maps));
> + if (!new_maps) {
> + pr_warning("alloc maps for object failed\n");
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + obj->maps_cap = new_cap;
> + obj->maps = new_maps;
> +
> + /* zero out new maps */
> + memset(obj->maps + obj->nr_maps, 0,
> + (obj->maps_cap - obj->nr_maps) * sizeof(*obj->maps));
> + /*
> + * fill all fd with -1 so won't close incorrect fd (fd=0 is stdin)
> + * when failure (zclose won't close negative fd)).
> + */
> + for (i = obj->nr_maps; i < obj->maps_cap; i++) {
> + obj->maps[i].fd = -1;
> + obj->maps[i].inner_map_fd = -1;
> + }
> +
> + return &obj->maps[obj->nr_maps++];
> }
>
> static int
> -bpf_object__init_internal_map(struct bpf_object *obj, struct bpf_map *map,
> - enum libbpf_map_type type, Elf_Data *data,
> - void **data_buff)
> +bpf_object__init_internal_map(struct bpf_object *obj, enum libbpf_map_type type,
> + Elf_Data *data, void **data_buff)
> {
> - struct bpf_map_def *def = &map->def;
> char map_name[BPF_OBJ_NAME_LEN];
> + struct bpf_map_def *def;
> + struct bpf_map *map;
> +
> + map = bpf_object__add_map(obj);
> + if (IS_ERR(map))
> + return PTR_ERR(map);
>
> map->libbpf_type = type;
> map->offset = ~(typeof(map->offset))0;
> @@ -789,6 +820,7 @@ bpf_object__init_internal_map(struct bpf_object *obj, struct bpf_map *map,
> return -ENOMEM;
> }
>
> + def = &map->def;
> def->type = BPF_MAP_TYPE_ARRAY;
> def->key_size = sizeof(int);
> def->value_size = data->d_size;
> @@ -808,29 +840,58 @@ bpf_object__init_internal_map(struct bpf_object *obj, struct bpf_map *map,
> return 0;
> }
>
> -static int bpf_object__init_maps(struct bpf_object *obj, int flags)
> +static int bpf_object__init_global_data_maps(struct bpf_object *obj)
> +{
> + int err;
> +
> + if (!obj->caps.global_data)
> + return 0;
> + /*
> + * Populate obj->maps with libbpf internal maps.
> + */
> + if (obj->efile.data_shndx >= 0) {
> + err = bpf_object__init_internal_map(obj, LIBBPF_MAP_DATA,
> + obj->efile.data,
> + &obj->sections.data);
> + if (err)
> + return err;
> + }
> + if (obj->efile.rodata_shndx >= 0) {
> + err = bpf_object__init_internal_map(obj, LIBBPF_MAP_RODATA,
> + obj->efile.rodata,
> + &obj->sections.rodata);
> + if (err)
> + return err;
> + }
> + if (obj->efile.bss_shndx >= 0) {
> + err = bpf_object__init_internal_map(obj, LIBBPF_MAP_BSS,
> + obj->efile.bss, NULL);
> + if (err)
> + return err;
> + }
> + return 0;
> +}
> +
> +static int bpf_object__init_user_maps(struct bpf_object *obj, bool strict)
> {
> - int i, map_idx, map_def_sz = 0, nr_syms, nr_maps = 0, nr_maps_glob = 0;
> - bool strict = !(flags & MAPS_RELAX_COMPAT);
> Elf_Data *symbols = obj->efile.symbols;
> + int i, map_def_sz = 0, nr_maps = 0, nr_syms;
> Elf_Data *data = NULL;
> - int ret = 0;
> + Elf_Scn *scn;
> +
> + if (obj->efile.maps_shndx < 0)
> + return 0;
>
> if (!symbols)
> return -EINVAL;
> - nr_syms = symbols->d_size / sizeof(GElf_Sym);
> -
> - if (obj->efile.maps_shndx >= 0) {
> - Elf_Scn *scn = elf_getscn(obj->efile.elf,
> - obj->efile.maps_shndx);
>
> - if (scn)
> - data = elf_getdata(scn, NULL);
> - if (!scn || !data) {
> - pr_warning("failed to get Elf_Data from map section %d\n",
> - obj->efile.maps_shndx);
> - return -EINVAL;
> - }
> + scn = elf_getscn(obj->efile.elf, obj->efile.maps_shndx);
> + if (scn)
> + data = elf_getdata(scn, NULL);
> + if (!scn || !data) {
> + pr_warning("failed to get Elf_Data from map section %d\n",
> + obj->efile.maps_shndx);
> + return -EINVAL;
> }
>
> /*
> @@ -840,16 +901,8 @@ static int bpf_object__init_maps(struct bpf_object *obj, int flags)
> *
> * TODO: Detect array of map and report error.
> */
> - if (obj->caps.global_data) {
> - if (obj->efile.data_shndx >= 0)
> - nr_maps_glob++;
> - if (obj->efile.rodata_shndx >= 0)
> - nr_maps_glob++;
> - if (obj->efile.bss_shndx >= 0)
> - nr_maps_glob++;
> - }
> -
> - for (i = 0; data && i < nr_syms; i++) {
> + nr_syms = symbols->d_size / sizeof(GElf_Sym);
> + for (i = 0; i < nr_syms; i++) {
> GElf_Sym sym;
>
> if (!gelf_getsym(symbols, i, &sym))
> @@ -858,79 +911,56 @@ static int bpf_object__init_maps(struct bpf_object *obj, int flags)
> continue;
> nr_maps++;
> }
> -
> - if (!nr_maps && !nr_maps_glob)
> - return 0;
> -
> /* Assume equally sized map definitions */
> - if (data) {
> - pr_debug("maps in %s: %d maps in %zd bytes\n", obj->path,
> - nr_maps, data->d_size);
> -
> - map_def_sz = data->d_size / nr_maps;
> - if (!data->d_size || (data->d_size % nr_maps) != 0) {
> - pr_warning("unable to determine map definition size "
> - "section %s, %d maps in %zd bytes\n",
> - obj->path, nr_maps, data->d_size);
> - return -EINVAL;
> - }
> - }
> -
> - nr_maps += nr_maps_glob;
> - obj->maps = calloc(nr_maps, sizeof(obj->maps[0]));
> - if (!obj->maps) {
> - pr_warning("alloc maps for object failed\n");
> - return -ENOMEM;
> - }
> - obj->nr_maps = nr_maps;
> -
> - for (i = 0; i < nr_maps; i++) {
> - /*
> - * fill all fd with -1 so won't close incorrect
> - * fd (fd=0 is stdin) when failure (zclose won't close
> - * negative fd)).
> - */
> - obj->maps[i].fd = -1;
> - obj->maps[i].inner_map_fd = -1;
> + pr_debug("maps in %s: %d maps in %zd bytes\n",
> + obj->path, nr_maps, data->d_size);
> +
> + map_def_sz = data->d_size / nr_maps;
> + if (!data->d_size || (data->d_size % nr_maps) != 0) {
> + pr_warning("unable to determine map definition size "
> + "section %s, %d maps in %zd bytes\n",
> + obj->path, nr_maps, data->d_size);
> + return -EINVAL;
> }
>
> - /*
> - * Fill obj->maps using data in "maps" section.
> - */
> - for (i = 0, map_idx = 0; data && i < nr_syms; i++) {
> + /* Fill obj->maps using data in "maps" section. */
> + for (i = 0; i < nr_syms; i++) {
> GElf_Sym sym;
> const char *map_name;
> struct bpf_map_def *def;
> + struct bpf_map *map;
>
> if (!gelf_getsym(symbols, i, &sym))
> continue;
> if (sym.st_shndx != obj->efile.maps_shndx)
> continue;
>
> - map_name = elf_strptr(obj->efile.elf,
> - obj->efile.strtabidx,
> + map = bpf_object__add_map(obj);
> + if (IS_ERR(map))
> + return PTR_ERR(map);
> +
> + map_name = elf_strptr(obj->efile.elf, obj->efile.strtabidx,
> sym.st_name);
> if (!map_name) {
> pr_warning("failed to get map #%d name sym string for obj %s\n",
> - map_idx, obj->path);
> + i, obj->path);
> return -LIBBPF_ERRNO__FORMAT;
> }
>
> - obj->maps[map_idx].libbpf_type = LIBBPF_MAP_UNSPEC;
> - obj->maps[map_idx].offset = sym.st_value;
> + map->libbpf_type = LIBBPF_MAP_UNSPEC;
> + map->offset = sym.st_value;
> if (sym.st_value + map_def_sz > data->d_size) {
> pr_warning("corrupted maps section in %s: last map \"%s\" too small\n",
> obj->path, map_name);
> return -EINVAL;
> }
>
> - obj->maps[map_idx].name = strdup(map_name);
> - if (!obj->maps[map_idx].name) {
> + map->name = strdup(map_name);
> + if (!map->name) {
> pr_warning("failed to alloc map name\n");
> return -ENOMEM;
> }
> - pr_debug("map %d is \"%s\"\n", map_idx,
> - obj->maps[map_idx].name);
> + pr_debug("map %d is \"%s\"\n", i, map->name);
> def = (struct bpf_map_def *)(data->d_buf + sym.st_value);
> /*
> * If the definition of the map in the object file fits in
> @@ -939,7 +969,7 @@ static int bpf_object__init_maps(struct bpf_object *obj, int flags)
> * calloc above.
> */
> if (map_def_sz <= sizeof(struct bpf_map_def)) {
> - memcpy(&obj->maps[map_idx].def, def, map_def_sz);
> + memcpy(&map->def, def, map_def_sz);
> } else {
> /*
> * Here the map structure being read is bigger than what
> @@ -959,37 +989,30 @@ static int bpf_object__init_maps(struct bpf_object *obj, int flags)
> return -EINVAL;
> }
> }
> - memcpy(&obj->maps[map_idx].def, def,
> - sizeof(struct bpf_map_def));
> + memcpy(&map->def, def, sizeof(struct bpf_map_def));
> }
> - map_idx++;
> }
> + return 0;
> +}
>
> - if (!obj->caps.global_data)
> - goto finalize;
> +static int bpf_object__init_maps(struct bpf_object *obj, int flags)
> +{
> + bool strict = !(flags & MAPS_RELAX_COMPAT);
> + int err;
>
> - /*
> - * Populate rest of obj->maps with libbpf internal maps.
> - */
> - if (obj->efile.data_shndx >= 0)
> - ret = bpf_object__init_internal_map(obj, &obj->maps[map_idx++],
> - LIBBPF_MAP_DATA,
> - obj->efile.data,
> - &obj->sections.data);
> - if (!ret && obj->efile.rodata_shndx >= 0)
> - ret = bpf_object__init_internal_map(obj, &obj->maps[map_idx++],
> - LIBBPF_MAP_RODATA,
> - obj->efile.rodata,
> - &obj->sections.rodata);
> - if (!ret && obj->efile.bss_shndx >= 0)
> - ret = bpf_object__init_internal_map(obj, &obj->maps[map_idx++],
> - LIBBPF_MAP_BSS,
> - obj->efile.bss, NULL);
> -finalize:
> - if (!ret)
> + err = bpf_object__init_user_maps(obj, strict);
> + if (err)
> + return err;
> +
> + err = bpf_object__init_global_data_maps(obj);
> + if (err)
> + return err;
> +
> + if (obj->nr_maps) {
> qsort(obj->maps, obj->nr_maps, sizeof(obj->maps[0]),
> compare_bpf_map);
> - return ret;
> + }
> + return 0;
> }
>
> static bool section_have_execinstr(struct bpf_object *obj, int idx)
> @@ -1262,14 +1285,10 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
> return -LIBBPF_ERRNO__FORMAT;
> }
> err = bpf_object__load_btf(obj, btf_data, btf_ext_data);
> - if (err)
> - return err;
> - if (bpf_object__has_maps(obj)) {
> + if (!err)
> err = bpf_object__init_maps(obj, flags);
> - if (err)
> - return err;
> - }
> - err = bpf_object__init_prog_names(obj);
> + if (!err)
> + err = bpf_object__init_prog_names(obj);
> return err;
> }
>
> --
> 2.17.1
>
^ permalink raw reply
* [PATCH net-next v3 6/6] taprio: Adjust timestamps for TCP packets.
From: Vedang Patel @ 2019-06-17 19:31 UTC (permalink / raw)
To: netdev
Cc: jeffrey.t.kirsher, davem, jhs, xiyou.wangcong, jiri,
intel-wired-lan, vinicius.gomes, l, Vedang Patel
In-Reply-To: <1560799870-18956-1-git-send-email-vedang.patel@intel.com>
When the taprio qdisc is running in "txtime offload" mode, it will
set the launchtime value (in skb->tstamp) for all the packets which do
not have the SO_TXTIME socket option. But, the TCP packets already have
this value set and it indicates the earliest departure time represented
in CLOCK_MONOTONIC clock.
We need to respect the timestamp set by the TCP subsystem. So, convert
this time to the clock which taprio is using and ensure that the packet
is not transmitted before the deadline set by TCP.
Signed-off-by: Vedang Patel <vedang.patel@intel.com>
---
net/sched/sch_taprio.c | 41 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index f63cc3a9e69a..ae261af16c13 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -22,6 +22,7 @@
#include <net/pkt_cls.h>
#include <net/sch_generic.h>
#include <net/sock.h>
+#include <net/tcp.h>
static LIST_HEAD(taprio_list);
static DEFINE_SPINLOCK(taprio_list_lock);
@@ -277,6 +278,41 @@ static inline ktime_t get_cycle_start(struct sched_gate_list *sched,
return ktime_sub(time, cycle_elapsed);
}
+/* This returns the tstamp value set by TCP in terms of the set clock. */
+static ktime_t get_tcp_tstamp(struct taprio_sched *q, struct sk_buff *skb)
+{
+ unsigned int offset = skb_network_offset(skb);
+ const struct ipv6hdr *ipv6h;
+ const struct iphdr *iph;
+ struct ipv6hdr _ipv6h;
+
+ ipv6h = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
+ if (!ipv6h)
+ return 0;
+
+ if (ipv6h->version == 4) {
+ iph = (struct iphdr *)ipv6h;
+ offset += iph->ihl * 4;
+
+ /* special-case 6in4 tunnelling, as that is a common way to get
+ * v6 connectivity in the home
+ */
+ if (iph->protocol == IPPROTO_IPV6) {
+ ipv6h = skb_header_pointer(skb, offset,
+ sizeof(_ipv6h), &_ipv6h);
+
+ if (!ipv6h || ipv6h->nexthdr != IPPROTO_TCP)
+ return 0;
+ } else if (iph->protocol != IPPROTO_TCP) {
+ return 0;
+ }
+ } else if (ipv6h->version == 6 && ipv6h->nexthdr != IPPROTO_TCP) {
+ return 0;
+ }
+
+ return ktime_mono_to_any(skb->skb_mstamp_ns, q->tk_offset);
+}
+
/* There are a few scenarios where we will have to modify the txtime from
* what is read from next_txtime in sched_entry. They are:
* 1. If txtime is in the past,
@@ -294,7 +330,7 @@ static inline ktime_t get_cycle_start(struct sched_gate_list *sched,
*/
static long get_packet_txtime(struct sk_buff *skb, struct Qdisc *sch)
{
- ktime_t transmit_end_time, interval_end, interval_start;
+ ktime_t transmit_end_time, interval_end, interval_start, tcp_tstamp;
struct taprio_sched *q = qdisc_priv(sch);
struct sched_gate_list *sched, *admin;
ktime_t minimum_time, now, txtime;
@@ -305,6 +341,9 @@ static long get_packet_txtime(struct sk_buff *skb, struct Qdisc *sch)
now = taprio_get_time(q);
minimum_time = ktime_add_ns(now, q->txtime_delay);
+ tcp_tstamp = get_tcp_tstamp(q, skb);
+ minimum_time = max_t(ktime_t, minimum_time, tcp_tstamp);
+
rcu_read_lock();
admin = rcu_dereference(q->admin_sched);
sched = rcu_dereference(q->oper_sched);
--
2.7.3
^ permalink raw reply related
* [PATCH net-next v3 4/6] taprio: Add support for txtime-assist mode.
From: Vedang Patel @ 2019-06-17 19:31 UTC (permalink / raw)
To: netdev
Cc: jeffrey.t.kirsher, davem, jhs, xiyou.wangcong, jiri,
intel-wired-lan, vinicius.gomes, l, Vedang Patel
In-Reply-To: <1560799870-18956-1-git-send-email-vedang.patel@intel.com>
Currently, we are seeing non-critical packets being transmitted outside of
their timeslice. We can confirm that the packets are being dequeued at the
right time. So, the delay is induced in the hardware side. The most likely
reason is the hardware queues are starving the lower priority queues.
In order to improve the performance of taprio, we will be making use of the
txtime feature provided by the ETF qdisc. For all the packets which do not
have the SO_TXTIME option set, taprio will set the transmit timestamp (set
in skb->tstamp) in this mode. TAPrio Qdisc will ensure that the transmit
time for the packet is set to when the gate is open. If SO_TXTIME is set,
the TAPrio qdisc will validate whether the timestamp (in skb->tstamp)
occurs when the gate corresponding to skb's traffic class is open.
Following two parameters added to support this mode:
- flags: used to enable txtime-assist mode. Will also be used to enable
other modes (like hardware offloading) later.
- txtime-delay: This indicates the minimum time it will take for the packet
to hit the wire. This is useful in determining whether we can transmit
the packet in the remaining time if the gate corresponding to the packet is
currently open.
An example configuration for enabling txtime-assist:
tc qdisc replace dev eth0 parent root handle 100 taprio \\
num_tc 3 \\
map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 \\
queues 1@0 1@0 1@0 \\
base-time 1558653424279842568 \\
sched-entry S 01 300000 \\
sched-entry S 02 300000 \\
sched-entry S 04 400000 \\
flags 0x1 \\
txtime-delay 40000 \\
clockid CLOCK_TAI
tc qdisc replace dev $IFACE parent 100:1 etf skip_sock_check \\
offload delta 200000 clockid CLOCK_TAI
Note that all the traffic classes are mapped to the same queue. This is
only possible in taprio when txtime-assist is enabled. Also, note that the
ETF Qdisc is enabled with offload mode set.
In this mode, if the packet's traffic class is open and the complete packet
can be transmitted, taprio will try to transmit the packet immediately.
This will be done by setting skb->tstamp to current_time + the time delta
indicated in the txtime-delay parameter. This parameter indicates the time
taken (in software) for packet to reach the network adapter.
If the packet cannot be transmitted in the current interval or if the
packet's traffic is not currently transmitting, the skb->tstamp is set to
the next available timestamp value. This is tracked in the next_launchtime
parameter in the struct sched_entry.
The behaviour w.r.t admin and oper schedules is not changed from what is
present in software mode.
The transmit time is already known in advance. So, we do not need the HR
timers to advance the schedule and wakeup the dequeue side of taprio. So,
HR timer won't be run when this mode is enabled.
Signed-off-by: Vedang Patel <vedang.patel@intel.com>
---
include/uapi/linux/pkt_sched.h | 4 +
net/sched/sch_taprio.c | 351 +++++++++++++++++++++++++++++++++++++++--
2 files changed, 338 insertions(+), 17 deletions(-)
diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h
index 69fc52e4d6bd..c085860ff637 100644
--- a/include/uapi/linux/pkt_sched.h
+++ b/include/uapi/linux/pkt_sched.h
@@ -1159,6 +1159,8 @@ enum {
* [TCA_TAPRIO_ATTR_SCHED_ENTRY_INTERVAL]
*/
+#define TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST 0x1
+
enum {
TCA_TAPRIO_ATTR_UNSPEC,
TCA_TAPRIO_ATTR_PRIOMAP, /* struct tc_mqprio_qopt */
@@ -1170,6 +1172,8 @@ enum {
TCA_TAPRIO_ATTR_ADMIN_SCHED, /* The admin sched, only used in dump */
TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME, /* s64 */
TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION, /* s64 */
+ TCA_TAPRIO_ATTR_FLAGS, /* u32 */
+ TCA_TAPRIO_ATTR_TXTIME_DELAY, /* s32 */
__TCA_TAPRIO_ATTR_MAX,
};
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index a41d7d4434ee..ab6080013666 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -21,12 +21,16 @@
#include <net/pkt_sched.h>
#include <net/pkt_cls.h>
#include <net/sch_generic.h>
+#include <net/sock.h>
static LIST_HEAD(taprio_list);
static DEFINE_SPINLOCK(taprio_list_lock);
#define TAPRIO_ALL_GATES_OPEN -1
+#define FLAGS_VALID(flags) (!((flags) & ~TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST))
+#define TXTIME_ASSIST_IS_ENABLED(flags) ((flags) & TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST)
+
struct sched_entry {
struct list_head list;
@@ -35,6 +39,7 @@ struct sched_entry {
* packet leaves after this time.
*/
ktime_t close_time;
+ ktime_t next_txtime;
atomic_t budget;
int index;
u32 gate_mask;
@@ -55,6 +60,7 @@ struct sched_gate_list {
struct taprio_sched {
struct Qdisc **qdiscs;
struct Qdisc *root;
+ u32 flags;
int clockid;
atomic64_t picos_per_byte; /* Using picoseconds because for 10Gbps+
* speeds it's sub-nanoseconds per byte
@@ -68,6 +74,7 @@ struct taprio_sched {
ktime_t (*get_time)(void);
struct hrtimer advance_timer;
struct list_head taprio_list;
+ int txtime_delay;
};
static ktime_t sched_base_time(const struct sched_gate_list *sched)
@@ -108,6 +115,237 @@ static void switch_schedules(struct taprio_sched *q,
*admin = NULL;
}
+/* Get how much time has been already elapsed in the current cycle. */
+static inline s32 get_cycle_time_elapsed(struct sched_gate_list *sched, ktime_t time)
+{
+ ktime_t time_since_sched_start;
+ s32 time_elapsed;
+
+ time_since_sched_start = ktime_sub(time, sched->base_time);
+ div_s64_rem(time_since_sched_start, sched->cycle_time, &time_elapsed);
+
+ return time_elapsed;
+}
+
+static ktime_t get_interval_end_time(struct sched_gate_list *sched,
+ struct sched_gate_list *admin,
+ struct sched_entry *entry,
+ ktime_t intv_start)
+{
+ s32 cycle_elapsed = get_cycle_time_elapsed(sched, intv_start);
+ ktime_t intv_end, cycle_ext_end, cycle_end;
+
+ cycle_end = ktime_add_ns(intv_start, sched->cycle_time - cycle_elapsed);
+ intv_end = ktime_add_ns(intv_start, entry->interval);
+ cycle_ext_end = ktime_add(cycle_end, sched->cycle_time_extension);
+
+ if (ktime_before(intv_end, cycle_end))
+ return intv_end;
+ else if (admin && admin != sched &&
+ ktime_after(admin->base_time, cycle_end) &&
+ ktime_before(admin->base_time, cycle_ext_end))
+ return admin->base_time;
+ else
+ return cycle_end;
+}
+
+static inline int length_to_duration(struct taprio_sched *q, int len)
+{
+ return (len * atomic64_read(&q->picos_per_byte)) / 1000;
+}
+
+/* Returns the entry corresponding to next available interval. If
+ * validate_interval is set, it only validates whether the timestamp occurs
+ * when the gate corresponding to the skb's traffic class is open.
+ */
+static struct sched_entry *find_entry_to_transmit(struct sk_buff *skb,
+ struct Qdisc *sch,
+ struct sched_gate_list *sched,
+ struct sched_gate_list *admin,
+ ktime_t time,
+ ktime_t *interval_start,
+ ktime_t *interval_end,
+ bool validate_interval)
+{
+ ktime_t curr_intv_start, curr_intv_end, cycle_end, packet_transmit_time;
+ ktime_t earliest_txtime = KTIME_MAX, txtime, cycle, transmit_end_time;
+ struct sched_entry *entry = NULL, *entry_found = NULL;
+ struct taprio_sched *q = qdisc_priv(sch);
+ struct net_device *dev = qdisc_dev(sch);
+ bool entry_available = false;
+ s32 cycle_elapsed;
+ int tc, n;
+
+ tc = netdev_get_prio_tc_map(dev, skb->priority);
+ packet_transmit_time = length_to_duration(q, qdisc_pkt_len(skb));
+
+ *interval_start = 0;
+ *interval_end = 0;
+
+ if (!sched)
+ return NULL;
+
+ cycle = sched->cycle_time;
+ cycle_elapsed = get_cycle_time_elapsed(sched, time);
+ curr_intv_end = ktime_sub_ns(time, cycle_elapsed);
+ cycle_end = ktime_add_ns(curr_intv_end, cycle);
+
+ list_for_each_entry(entry, &sched->entries, list) {
+ curr_intv_start = curr_intv_end;
+ curr_intv_end = get_interval_end_time(sched, admin, entry,
+ curr_intv_start);
+
+ if (ktime_after(curr_intv_start, cycle_end))
+ break;
+
+ if (!(entry->gate_mask & BIT(tc)) ||
+ packet_transmit_time > entry->interval)
+ continue;
+
+ txtime = entry->next_txtime;
+
+ if (ktime_before(txtime, time) || validate_interval) {
+ transmit_end_time = ktime_add_ns(time, packet_transmit_time);
+ if ((ktime_before(curr_intv_start, time) &&
+ ktime_before(transmit_end_time, curr_intv_end)) ||
+ (ktime_after(curr_intv_start, time) && !validate_interval)) {
+ entry_found = entry;
+ *interval_start = curr_intv_start;
+ *interval_end = curr_intv_end;
+ break;
+ } else if (!entry_available && !validate_interval) {
+ /* Here, we are just trying to find out the
+ * first available interval in the next cycle.
+ */
+ entry_available = 1;
+ entry_found = entry;
+ *interval_start = ktime_add_ns(curr_intv_start, cycle);
+ *interval_end = ktime_add_ns(curr_intv_end, cycle);
+ }
+ } else if (ktime_before(txtime, earliest_txtime) &&
+ !entry_available) {
+ earliest_txtime = txtime;
+ entry_found = entry;
+ n = div_s64(ktime_sub(txtime, curr_intv_start), cycle);
+ *interval_start = ktime_add(curr_intv_start, n * cycle);
+ *interval_end = ktime_add(curr_intv_end, n * cycle);
+ }
+ }
+
+ return entry_found;
+}
+
+static bool is_valid_interval(struct sk_buff *skb, struct Qdisc *sch)
+{
+ struct taprio_sched *q = qdisc_priv(sch);
+ struct sched_gate_list *sched, *admin;
+ ktime_t interval_start, interval_end;
+ struct sched_entry *entry;
+
+ rcu_read_lock();
+ sched = rcu_dereference(q->oper_sched);
+ admin = rcu_dereference(q->admin_sched);
+
+ entry = find_entry_to_transmit(skb, sch, sched, admin, skb->tstamp,
+ &interval_start, &interval_end, true);
+ rcu_read_unlock();
+
+ return entry;
+}
+
+static inline ktime_t get_cycle_start(struct sched_gate_list *sched,
+ ktime_t time)
+{
+ ktime_t cycle_elapsed;
+
+ cycle_elapsed = get_cycle_time_elapsed(sched, time);
+
+ return ktime_sub(time, cycle_elapsed);
+}
+
+/* There are a few scenarios where we will have to modify the txtime from
+ * what is read from next_txtime in sched_entry. They are:
+ * 1. If txtime is in the past,
+ * a. The gate for the traffic class is currently open and packet can be
+ * transmitted before it closes, schedule the packet right away.
+ * b. If the gate corresponding to the traffic class is going to open later
+ * in the cycle, set the txtime of packet to the interval start.
+ * 2. If txtime is in the future, there are packets corresponding to the
+ * current traffic class waiting to be transmitted. So, the following
+ * possibilities exist:
+ * a. We can transmit the packet before the window containing the txtime
+ * closes.
+ * b. The window might close before the transmission can be completed
+ * successfully. So, schedule the packet in the next open window.
+ */
+static long get_packet_txtime(struct sk_buff *skb, struct Qdisc *sch)
+{
+ ktime_t transmit_end_time, interval_end, interval_start;
+ struct taprio_sched *q = qdisc_priv(sch);
+ struct sched_gate_list *sched, *admin;
+ ktime_t minimum_time, now, txtime;
+ int len, packet_transmit_time;
+ struct sched_entry *entry;
+ bool sched_changed;
+
+ now = q->get_time();
+ minimum_time = ktime_add_ns(now, q->txtime_delay);
+
+ rcu_read_lock();
+ admin = rcu_dereference(q->admin_sched);
+ sched = rcu_dereference(q->oper_sched);
+ if (admin && ktime_after(minimum_time, admin->base_time))
+ switch_schedules(q, &admin, &sched);
+
+ /* Until the schedule starts, all the queues are open */
+ if (!sched || ktime_before(minimum_time, sched->base_time)) {
+ txtime = minimum_time;
+ goto done;
+ }
+
+ len = qdisc_pkt_len(skb);
+ packet_transmit_time = length_to_duration(q, len);
+
+ do {
+ sched_changed = 0;
+
+ entry = find_entry_to_transmit(skb, sch, sched, admin,
+ minimum_time,
+ &interval_start, &interval_end,
+ false);
+ if (!entry) {
+ txtime = 0;
+ goto done;
+ }
+
+ txtime = entry->next_txtime;
+ txtime = max_t(ktime_t, txtime, minimum_time);
+ txtime = max_t(ktime_t, txtime, interval_start);
+
+ if (admin && admin != sched &&
+ ktime_after(txtime, admin->base_time)) {
+ sched = admin;
+ sched_changed = 1;
+ continue;
+ }
+
+ transmit_end_time = ktime_add(txtime, packet_transmit_time);
+ minimum_time = transmit_end_time;
+
+ /* Update the txtime of current entry to the next time it's
+ * interval starts.
+ */
+ if (ktime_after(transmit_end_time, interval_end))
+ entry->next_txtime = ktime_add(interval_start, sched->cycle_time);
+ } while (sched_changed || ktime_after(transmit_end_time, interval_end));
+
+ entry->next_txtime = transmit_end_time;
+
+done:
+ rcu_read_unlock();
+ return txtime;
+}
+
static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff **to_free)
{
@@ -121,6 +359,15 @@ static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
if (unlikely(!child))
return qdisc_drop(skb, sch, to_free);
+ if (skb->sk && sock_flag(skb->sk, SOCK_TXTIME)) {
+ if (!is_valid_interval(skb, sch))
+ return qdisc_drop(skb, sch, to_free);
+ } else if (TXTIME_ASSIST_IS_ENABLED(q->flags)) {
+ skb->tstamp = get_packet_txtime(skb, sch);
+ if (!skb->tstamp)
+ return qdisc_drop(skb, sch, to_free);
+ }
+
qdisc_qstats_backlog_inc(sch, skb);
sch->q.qlen++;
@@ -156,6 +403,9 @@ static struct sk_buff *taprio_peek(struct Qdisc *sch)
if (!skb)
continue;
+ if (TXTIME_ASSIST_IS_ENABLED(q->flags))
+ return skb;
+
prio = skb->priority;
tc = netdev_get_prio_tc_map(dev, prio);
@@ -168,11 +418,6 @@ static struct sk_buff *taprio_peek(struct Qdisc *sch)
return NULL;
}
-static inline int length_to_duration(struct taprio_sched *q, int len)
-{
- return div_u64(len * atomic64_read(&q->picos_per_byte), 1000);
-}
-
static void taprio_set_budget(struct taprio_sched *q, struct sched_entry *entry)
{
atomic_set(&entry->budget,
@@ -216,6 +461,13 @@ static struct sk_buff *taprio_dequeue(struct Qdisc *sch)
if (unlikely(!child))
continue;
+ if (TXTIME_ASSIST_IS_ENABLED(q->flags)) {
+ skb = child->ops->dequeue(child);
+ if (!skb)
+ continue;
+ goto skb_found;
+ }
+
skb = child->ops->peek(child);
if (!skb)
continue;
@@ -246,6 +498,7 @@ static struct sk_buff *taprio_dequeue(struct Qdisc *sch)
if (unlikely(!skb))
goto done;
+skb_found:
qdisc_bstats_update(sch, skb);
qdisc_qstats_backlog_dec(sch, skb);
sch->q.qlen--;
@@ -522,7 +775,8 @@ static int parse_taprio_schedule(struct nlattr **tb,
static int taprio_parse_mqprio_opt(struct net_device *dev,
struct tc_mqprio_qopt *qopt,
- struct netlink_ext_ack *extack)
+ struct netlink_ext_ack *extack,
+ u32 taprio_flags)
{
int i, j;
@@ -570,6 +824,9 @@ static int taprio_parse_mqprio_opt(struct net_device *dev,
return -EINVAL;
}
+ if (TXTIME_ASSIST_IS_ENABLED(taprio_flags))
+ continue;
+
/* Verify that the offset and counts do not overlap */
for (j = i + 1; j < qopt->num_tc; j++) {
if (last > qopt->offset[j]) {
@@ -700,6 +957,18 @@ static int taprio_dev_notifier(struct notifier_block *nb, unsigned long event,
return NOTIFY_DONE;
}
+static void setup_txtime(struct taprio_sched *q,
+ struct sched_gate_list *sched, ktime_t base)
+{
+ struct sched_entry *entry;
+ u32 interval = 0;
+
+ list_for_each_entry(entry, &sched->entries, list) {
+ entry->next_txtime = ktime_add_ns(base, interval);
+ interval += entry->interval;
+ }
+}
+
static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
struct netlink_ext_ack *extack)
{
@@ -708,6 +977,7 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
struct taprio_sched *q = qdisc_priv(sch);
struct net_device *dev = qdisc_dev(sch);
struct tc_mqprio_qopt *mqprio = NULL;
+ u32 taprio_flags = 0;
int i, err, clockid;
unsigned long flags;
ktime_t start;
@@ -720,7 +990,21 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
if (tb[TCA_TAPRIO_ATTR_PRIOMAP])
mqprio = nla_data(tb[TCA_TAPRIO_ATTR_PRIOMAP]);
- err = taprio_parse_mqprio_opt(dev, mqprio, extack);
+ if (tb[TCA_TAPRIO_ATTR_FLAGS]) {
+ taprio_flags = nla_get_u32(tb[TCA_TAPRIO_ATTR_FLAGS]);
+
+ if (q->flags != 0 && q->flags != taprio_flags) {
+ NL_SET_ERR_MSG_MOD(extack, "Changing 'flags' of a running schedule is not supported");
+ return -EOPNOTSUPP;
+ } else if (!FLAGS_VALID(taprio_flags)) {
+ NL_SET_ERR_MSG_MOD(extack, "Specified 'flags' are not valid");
+ return -EINVAL;
+ }
+
+ q->flags = taprio_flags;
+ }
+
+ err = taprio_parse_mqprio_opt(dev, mqprio, extack, taprio_flags);
if (err < 0)
return err;
@@ -779,7 +1063,18 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
/* Protects against enqueue()/dequeue() */
spin_lock_bh(qdisc_lock(sch));
- if (!hrtimer_active(&q->advance_timer)) {
+ if (tb[TCA_TAPRIO_ATTR_TXTIME_DELAY]) {
+ if (!TXTIME_ASSIST_IS_ENABLED(q->flags)) {
+ NL_SET_ERR_MSG_MOD(extack, "txtime-delay can only be set when txtime-assist mode is enabled");
+ err = -EINVAL;
+ goto unlock;
+ }
+
+ q->txtime_delay = nla_get_s32(tb[TCA_TAPRIO_ATTR_TXTIME_DELAY]);
+ }
+
+ if (!TXTIME_ASSIST_IS_ENABLED(taprio_flags) &&
+ !hrtimer_active(&q->advance_timer)) {
hrtimer_init(&q->advance_timer, q->clockid, HRTIMER_MODE_ABS);
q->advance_timer.function = advance_sched;
}
@@ -822,20 +1117,35 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
goto unlock;
}
- setup_first_close_time(q, new_admin, start);
+ if (TXTIME_ASSIST_IS_ENABLED(taprio_flags)) {
+ setup_txtime(q, new_admin, start);
- /* Protects against advance_sched() */
- spin_lock_irqsave(&q->current_entry_lock, flags);
+ if (!oper) {
+ rcu_assign_pointer(q->oper_sched, new_admin);
+ err = 0;
+ new_admin = NULL;
+ goto unlock;
+ }
+
+ rcu_assign_pointer(q->admin_sched, new_admin);
+ if (admin)
+ call_rcu(&admin->rcu, taprio_free_sched_cb);
+ } else {
+ setup_first_close_time(q, new_admin, start);
- taprio_start_sched(sch, start, new_admin);
+ /* Protects against advance_sched() */
+ spin_lock_irqsave(&q->current_entry_lock, flags);
- rcu_assign_pointer(q->admin_sched, new_admin);
- if (admin)
- call_rcu(&admin->rcu, taprio_free_sched_cb);
- new_admin = NULL;
+ taprio_start_sched(sch, start, new_admin);
- spin_unlock_irqrestore(&q->current_entry_lock, flags);
+ rcu_assign_pointer(q->admin_sched, new_admin);
+ if (admin)
+ call_rcu(&admin->rcu, taprio_free_sched_cb);
+ spin_unlock_irqrestore(&q->current_entry_lock, flags);
+ }
+
+ new_admin = NULL;
err = 0;
unlock:
@@ -1073,6 +1383,13 @@ static int taprio_dump(struct Qdisc *sch, struct sk_buff *skb)
if (nla_put_s32(skb, TCA_TAPRIO_ATTR_SCHED_CLOCKID, q->clockid))
goto options_error;
+ if (q->flags && nla_put_u32(skb, TCA_TAPRIO_ATTR_FLAGS, q->flags))
+ goto options_error;
+
+ if (q->txtime_delay &&
+ nla_put_s32(skb, TCA_TAPRIO_ATTR_TXTIME_DELAY, q->txtime_delay))
+ goto options_error;
+
if (oper && dump_schedule(skb, oper))
goto options_error;
--
2.7.3
^ permalink raw reply related
* [PATCH net-next v3 5/6] taprio: make clock reference conversions easier
From: Vedang Patel @ 2019-06-17 19:31 UTC (permalink / raw)
To: netdev
Cc: jeffrey.t.kirsher, davem, jhs, xiyou.wangcong, jiri,
intel-wired-lan, vinicius.gomes, l, Vedang Patel
In-Reply-To: <1560799870-18956-1-git-send-email-vedang.patel@intel.com>
Later in this series we will need to transform from
CLOCK_MONOTONIC (used in TCP) to the clock reference used in TAPRIO.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
Signed-off-by: Vedang Patel <vedang.patel@intel.com>
---
net/sched/sch_taprio.c | 30 ++++++++++++++++++++++--------
1 file changed, 22 insertions(+), 8 deletions(-)
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index ab6080013666..f63cc3a9e69a 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -61,6 +61,7 @@ struct taprio_sched {
struct Qdisc **qdiscs;
struct Qdisc *root;
u32 flags;
+ enum tk_offsets tk_offset;
int clockid;
atomic64_t picos_per_byte; /* Using picoseconds because for 10Gbps+
* speeds it's sub-nanoseconds per byte
@@ -71,7 +72,6 @@ struct taprio_sched {
struct sched_entry __rcu *current_entry;
struct sched_gate_list __rcu *oper_sched;
struct sched_gate_list __rcu *admin_sched;
- ktime_t (*get_time)(void);
struct hrtimer advance_timer;
struct list_head taprio_list;
int txtime_delay;
@@ -85,6 +85,20 @@ static ktime_t sched_base_time(const struct sched_gate_list *sched)
return ns_to_ktime(sched->base_time);
}
+static inline ktime_t taprio_get_time(struct taprio_sched *q)
+{
+ ktime_t mono = ktime_get();
+
+ switch (q->tk_offset) {
+ case TK_OFFS_MAX:
+ return mono;
+ default:
+ return ktime_mono_to_any(mono, q->tk_offset);
+ }
+
+ return KTIME_MAX;
+}
+
static void taprio_free_sched_cb(struct rcu_head *head)
{
struct sched_gate_list *sched = container_of(head, struct sched_gate_list, rcu);
@@ -288,7 +302,7 @@ static long get_packet_txtime(struct sk_buff *skb, struct Qdisc *sch)
struct sched_entry *entry;
bool sched_changed;
- now = q->get_time();
+ now = taprio_get_time(q);
minimum_time = ktime_add_ns(now, q->txtime_delay);
rcu_read_lock();
@@ -479,7 +493,7 @@ static struct sk_buff *taprio_dequeue(struct Qdisc *sch)
continue;
len = qdisc_pkt_len(skb);
- guard = ktime_add_ns(q->get_time(),
+ guard = ktime_add_ns(taprio_get_time(q),
length_to_duration(q, len));
/* In the case that there's no gate entry, there's no
@@ -848,7 +862,7 @@ static int taprio_get_start_time(struct Qdisc *sch,
s64 n;
base = sched_base_time(sched);
- now = q->get_time();
+ now = taprio_get_time(q);
if (ktime_after(base, now)) {
*start = base;
@@ -1094,16 +1108,16 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
switch (q->clockid) {
case CLOCK_REALTIME:
- q->get_time = ktime_get_real;
+ q->tk_offset = TK_OFFS_REAL;
break;
case CLOCK_MONOTONIC:
- q->get_time = ktime_get;
+ q->tk_offset = TK_OFFS_MAX;
break;
case CLOCK_BOOTTIME:
- q->get_time = ktime_get_boottime;
+ q->tk_offset = TK_OFFS_BOOT;
break;
case CLOCK_TAI:
- q->get_time = ktime_get_clocktai;
+ q->tk_offset = TK_OFFS_TAI;
break;
default:
NL_SET_ERR_MSG(extack, "Invalid 'clockid'");
--
2.7.3
^ 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