> nfp: bpf: perf event output helpers support
>
> Add support for the perf_event_output family of helpers.
>
> The implementation on the NFP will not match the host code exactly.
> The state of the host map and rings is unknown to the device, hence
> device can't return errors when rings are not installed. The device
> simply packs the data into a firmware notification message and sends
> it over to the host, returning success to the program.
>
> There is no notion of a host CPU on the device when packets are being
> processed. Device will only offload programs which set BPF_F_CURRENT_CPU.
> Still, if map index doesn't match CPU no error will be returned (see
> above).
>
> Dropped/lost firmware notification messages will not cause "lost
> events" event on the perf ring, they are only visible via device
> error counters.
>
> Firmware notification messages may also get reordered in respect
> to the packets which caused their generation.
>
> Signed-off-by: Jakub Kicinski <[email protected]>
> Reviewed-by: Quentin Monnet <[email protected]>
> Signed-off-by: Daniel Borkmann <[email protected]>
>
> diff --git a/drivers/net/ethernet/netronome/nfp/bpf/offload.c b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
> index e3ead906cc60..4db0ac1e42a8 100644
> --- a/drivers/net/ethernet/netronome/nfp/bpf/offload.c
> +++ b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
> @@ -441,6 +441,53 @@ int nfp_ndo_bpf(struct nfp_app *app, struct nfp_net *nn, struct netdev_bpf *bpf)
> }
> }
>
> +static unsigned long
> +nfp_bpf_perf_event_copy(void *dst, const void *src,
> + unsigned long off, unsigned long len)
> +{
> + memcpy(dst, src + off, len);
> + return 0;
> +}
> +
> +int nfp_bpf_event_output(struct nfp_app_bpf *bpf, struct sk_buff *skb)
> +{
> + struct cmsg_bpf_event *cbe = (void *)skb->data;
> + u32 pkt_size, data_size;
> + struct bpf_map *map;
> +
> + if (skb->len < sizeof(struct cmsg_bpf_event))
> + goto err_drop;
> +
> + pkt_size = be32_to_cpu(cbe->pkt_size);
> + data_size = be32_to_cpu(cbe->data_size);
> + map = (void *)(unsigned long)be64_to_cpu(cbe->map_ptr);
> +
> + if (skb->len < sizeof(struct cmsg_bpf_event) + pkt_size + data_size)
> + goto err_drop;
> + if (cbe->hdr.ver != CMSG_MAP_ABI_VERSION)
> + goto err_drop;
> +
> + rcu_read_lock();
> + if (!rhashtable_lookup_fast(&bpf->maps_neutral, &map,
> + nfp_bpf_maps_neutral_params)) {
> + rcu_read_unlock();
> + pr_warn("perf event: dest map pointer %px not recognized, dropping event\n",
> + map);
Please don't use %px on kernel pointers unless you absolutely have
to[1]. It seems like this value wouldn't be actionable here, so likely
it's best to just remove its use entirely.
-Kees
[1] https://www.spinics.net/lists/kernel/msg2671068.html
--
Kees Cook
Pixel Security
On Wed, 6 Jun 2018 22:15:04 -0700, Kees Cook wrote:
> > + rcu_read_lock();
> > + if (!rhashtable_lookup_fast(&bpf->maps_neutral, &map,
> > + nfp_bpf_maps_neutral_params)) {
> > + rcu_read_unlock();
> > + pr_warn("perf event: dest map pointer %px not recognized, dropping event\n",
> > + map);
>
> Please don't use %px on kernel pointers unless you absolutely have
> to[1]. It seems like this value wouldn't be actionable here, so likely
> it's best to just remove its use entirely.
We're using kernel pointer as an opaque handle when communicating with
the device. We need the actual value to correlate things. Maybe I used
the %px slightly out of spite there, because I forgot %p is now useless
and wasted half an hour on debugging an endian issue :S
This message can only really trigger when root loads a specific BPF map
onto the device and FW is buggy. Can I fix it in -next? I'm making
changes to this part of the code anyway.
On Thu, Jun 7, 2018 at 9:33 AM, Jakub Kicinski
<[email protected]> wrote:
> On Wed, 6 Jun 2018 22:15:04 -0700, Kees Cook wrote:
>> > + rcu_read_lock();
>> > + if (!rhashtable_lookup_fast(&bpf->maps_neutral, &map,
>> > + nfp_bpf_maps_neutral_params)) {
>> > + rcu_read_unlock();
>> > + pr_warn("perf event: dest map pointer %px not recognized, dropping event\n",
>> > + map);
>>
>> Please don't use %px on kernel pointers unless you absolutely have
>> to[1]. It seems like this value wouldn't be actionable here, so likely
>> it's best to just remove its use entirely.
>
> We're using kernel pointer as an opaque handle when communicating with
> the device. We need the actual value to correlate things. Maybe I used
> the %px slightly out of spite there, because I forgot %p is now useless
> and wasted half an hour on debugging an endian issue :S
>
> This message can only really trigger when root loads a specific BPF map
> onto the device and FW is buggy. Can I fix it in -next? I'm making
> changes to this part of the code anyway.
That'd be fine by me, thanks!
-Kees
--
Kees Cook
Pixel Security