* Re: [PATCH] ptp_qoriq: use div_u64/div_u64_rem for 64-bit division
From: David Miller @ 2018-08-06 17:43 UTC (permalink / raw)
To: yangbo.lu; +Cc: netdev, richardcochran, linux-kernel
In-Reply-To: <20180806043911.15437-1-yangbo.lu@nxp.com>
From: Yangbo Lu <yangbo.lu@nxp.com>
Date: Mon, 6 Aug 2018 12:39:11 +0800
> This is a fix-up patch for below build issue with multi_v7_defconfig.
>
> drivers/ptp/ptp_qoriq.o: In function `qoriq_ptp_probe':
> ptp_qoriq.c:(.text+0xd0c): undefined reference to `__aeabi_uldivmod'
>
> Fixes: 91305f281262 ("ptp_qoriq: support automatic configuration for ptp timer")
> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] net: avoid unnecessary sock_flag() check when enable timestamp
From: David Miller @ 2018-08-06 17:43 UTC (permalink / raw)
To: laoar.shao; +Cc: netdev, linux-kernel
In-Reply-To: <1533527822-3324-1-git-send-email-laoar.shao@gmail.com>
From: Yafang Shao <laoar.shao@gmail.com>
Date: Mon, 6 Aug 2018 11:57:02 +0800
> The sock_flag() check is alreay inside sock_enable_timestamp(), so it is
> unnecessary checking it in the caller.
>
> void sock_enable_timestamp(struct sock *sk, int flag)
> {
> if (!sock_flag(sk, flag)) {
> ...
> }
> }
>
> Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next V2] vhost: switch to use new message format
From: David Miller @ 2018-08-06 17:41 UTC (permalink / raw)
To: jasowang; +Cc: mst, kvm, virtualization, netdev, linux-kernel
In-Reply-To: <1533525467-17787-1-git-send-email-jasowang@redhat.com>
From: Jason Wang <jasowang@redhat.com>
Date: Mon, 6 Aug 2018 11:17:47 +0800
> We use to have message like:
>
> struct vhost_msg {
> int type;
> union {
> struct vhost_iotlb_msg iotlb;
> __u8 padding[64];
> };
> };
>
> Unfortunately, there will be a hole of 32bit in 64bit machine because
> of the alignment. This leads a different formats between 32bit API and
> 64bit API. What's more it will break 32bit program running on 64bit
> machine.
>
> So fixing this by introducing a new message type with an explicit
> 32bit reserved field after type like:
>
> struct vhost_msg_v2 {
> __u32 type;
> __u32 reserved;
> union {
> struct vhost_iotlb_msg iotlb;
> __u8 padding[64];
> };
> };
>
> We will have a consistent ABI after switching to use this. To enable
> this capability, introduce a new ioctl (VHOST_SET_BAKCEND_FEATURE) for
> userspace to enable this feature (VHOST_BACKEND_F_IOTLB_V2).
>
> Fixes: 6b1e6cc7855b ("vhost: new device IOTLB API")
> Signed-off-by: Jason Wang <jasowang@redhat.com>
> ---
> Changes from V1:
> - use __u32 instead of int for type
Applied, thanks Jason.
^ permalink raw reply
* Re: [PATCH v3 net-next 5/9] net: stmmac: Add MDIO related functions for XGMAC2
From: Florian Fainelli @ 2018-08-06 15:25 UTC (permalink / raw)
To: Jose Abreu, netdev
Cc: David S. Miller, Joao Pinto, Giuseppe Cavallaro, Alexandre Torgue,
Andrew Lunn
In-Reply-To: <982b8bed-e11c-2f94-4f7d-21e358ffc0c0@synopsys.com>
On August 6, 2018 12:59:54 AM PDT, Jose Abreu <Jose.Abreu@synopsys.com> wrote:
>On 03-08-2018 20:06, Florian Fainelli wrote:
>> On 08/03/2018 08:50 AM, Jose Abreu wrote:
>>> Add the MDIO related funcionalities for the new IP block XGMAC2.
>>>
>>> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
>>> Cc: David S. Miller <davem@davemloft.net>
>>> Cc: Joao Pinto <jpinto@synopsys.com>
>>> Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
>>> Cc: Alexandre Torgue <alexandre.torgue@st.com>
>>> Cc: Andrew Lunn <andrew@lunn.ch>
>>> ---
>>> +satic int stmmac_xgmac2_c22_format(struct stmmac_priv *priv, int
>phyaddr,
>>> + int phyreg, u32 *hw_addr)
>>> +{
>>> + unsigned int mii_data = priv->hw->mii.data;
>>> + u32 tmp;
>>> +
>>> + /* HW does not support C22 addr >= 4 */
>>> + if (phyaddr >= 4)
>>> + return -ENODEV;
>> It would be nice if this could be moved at probe time so you don't
>have
>> to wait until you connect to the PHY, read its PHY OUI and find out
>it
>> has a MDIO address >= 4. Not a blocker, but something that could be
>> improved further on.
>>
>> In premise you could even scan the MDIO bus' device tree node, and
>find
>> that out ahead of time.
>
>Oh, but I use phylib ... I only provide the read/write callbacks
>so I think we should avoid duplicating the code that's already in
>the phylib ... No?
You can always extract the code that scans a MDIO bus into a helper function and make it parametrized with a callback of some kind. In that case I would be fine with you open coding the MDIO bus scan to find out if there is an address >= 4.
>
>>
>>> + /* Wait until any existing MII operation is complete */
>>> + if (readl_poll_timeout(priv->ioaddr + mii_data, tmp,
>>> + !(tmp & MII_XGMAC_BUSY), 100, 10000))
>>> + return -EBUSY;
>>> +
>>> + /* Set port as Clause 22 */
>>> + tmp = readl(priv->ioaddr + XGMAC_MDIO_C22P);
>>> + tmp |= BIT(phyaddr);
>> Since the registers are being Read/Modify/Write here, don't you need
>to
>> clear the previous address bits as well?
>>
>> You probably did not encounter any problems in your testing if you
>had
>> only one PHY on the MDIO bus, but this is not something that is
>> necessarily true, e.g: if you have an Ethernet switch, several MDIO
>bus
>> addresses are going to be responding.
>>
>> Your MDIO bus implementation must be able to support one transaction
>> with one PHY address and the next transaction with another PHY
>address ,
>> etc...
>>
>> That is something that should be easy to fix and be resubmitted as
>part
>> of v4.
>
>I'm not following you here... I only set/unset the bit for the
>corresponding phyaddr that phylib wants to read/write. Why would
>I clear the remaining addresses?
Because this is all about transactions, the HW must be in a state that it will be able to perform that transaction correctly. So here for instance if you needed to support a C45 transaction you would have to clear that bit for that particular PHY address. Since you don't appear to support those yet then yes the code appears fine though it would not hurt if you did clear all other PHY's c22 bits to make it clear what this does.
--
Florian
^ permalink raw reply
* Re: [PATCH v2] net/bridge/br_multicast: remove redundant variable "err"
From: David Miller @ 2018-08-06 17:34 UTC (permalink / raw)
To: zhongjiang; +Cc: stephen, netdev, linux-kernel
In-Reply-To: <1533524843-51236-1-git-send-email-zhongjiang@huawei.com>
From: zhong jiang <zhongjiang@huawei.com>
Date: Mon, 6 Aug 2018 11:07:23 +0800
> The err is not modified after initalization, So remove it and make
> it to be void function.
>
> Signed-off-by: zhong jiang <zhongjiang@huawei.com>
> ---
> v1->v2:
> - The initalization of err to '0' is unnecesary. so drop the change
Applied, thank you.
^ permalink raw reply
* Re: [PATCH v4] selftests: add headers_install to lib.mk
From: Shuah Khan @ 2018-08-06 17:03 UTC (permalink / raw)
To: Anders Roxell
Cc: Masahiro Yamada, Michal Marek, Bamvor Zhang, brgl, Paolo Bonzini,
Andrew Morton, Mike Rapoport, aarcange, linux-kbuild,
Linux Kernel Mailing List, open list:KERNEL SELFTEST FRAMEWORK,
Networking, Shuah Khan
In-Reply-To: <CADYN=9LSA60E4mFwrbeY-RGi4kZV6hO0ygz0-C6QB3+KKaoxQg@mail.gmail.com>
Hi Anders,
On 07/25/2018 10:08 AM, Anders Roxell wrote:
> On Tue, 24 Jul 2018 at 19:11, Shuah Khan <shuah@kernel.org> wrote:
>>
>> On 07/23/2018 02:49 PM, Anders Roxell wrote:
>>> On Thu, 7 Jun 2018 at 13:09, Anders Roxell <anders.roxell@linaro.org> wrote:
>>>>
>>>> If the kernel headers aren't installed we can't build all the tests.
>>>> Add a new make target rule 'khdr' in the file lib.mk to generate the
>>>> kernel headers and that gets include for every test-dir Makefile that
>>>> includes lib.mk If the testdir in turn have its own sub-dirs the
>>>> top_srcdir needs to be set to the linux-rootdir to be able to generate
>>>> the kernel headers.
>>>>
>>>> Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
>>>> Reviewed-by: Fathi Boudra <fathi.boudra@linaro.org>
>>>> ---
>>>> Makefile | 14 +-------------
>>>> scripts/subarch.include | 13 +++++++++++++
>>>> tools/testing/selftests/android/Makefile | 2 +-
>>>> tools/testing/selftests/android/ion/Makefile | 2 ++
>>>> tools/testing/selftests/futex/functional/Makefile | 1 +
>>>> tools/testing/selftests/gpio/Makefile | 7 ++-----
>>>> tools/testing/selftests/kvm/Makefile | 7 ++-----
>>>> tools/testing/selftests/lib.mk | 12 ++++++++++++
>>>> tools/testing/selftests/net/Makefile | 1 +
>>>> .../selftests/networking/timestamping/Makefile | 1 +
>>>> tools/testing/selftests/vm/Makefile | 4 ----
>>>> 11 files changed, 36 insertions(+), 28 deletions(-)
>>>> create mode 100644 scripts/subarch.include
>>>>
>>>> diff --git a/Makefile b/Makefile
>>>> index 6b9aea95ae3a..8050072300fa 100644
>>>> --- a/Makefile
>>>> +++ b/Makefile
>>>> @@ -286,19 +286,7 @@ KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
>>>> KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
>>>> export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
>>>>
>>>> -# SUBARCH tells the usermode build what the underlying arch is. That is set
>>>> -# first, and if a usermode build is happening, the "ARCH=um" on the command
>>>> -# line overrides the setting of ARCH below. If a native build is happening,
>>>> -# then ARCH is assigned, getting whatever value it gets normally, and
>>>> -# SUBARCH is subsequently ignored.
>>>> -
>>>> -SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
>>>> - -e s/sun4u/sparc64/ \
>>>> - -e s/arm.*/arm/ -e s/sa110/arm/ \
>>>> - -e s/s390x/s390/ -e s/parisc64/parisc/ \
>>>> - -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
>>>> - -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \
>>>> - -e s/riscv.*/riscv/)
>>>> +include scripts/subarch.include
>>
>> What is the reason for this SUBARCH block move to to scripts/subarch.include?
>> Is this necessary for adding headers install dependency to lib.mk?
>
> This is needed to create headers for cross build.
>
I am sorry for the delay on this patch. I am going to get this into 4.19.
If anybody has objections, please let me.
Anders! Will be able to rebase the patch and send me the latest. I think
I have Acks from kvm, android, and vm so far.
thanks,
-- Shuah
^ permalink raw reply
* [PATCH] net: thunderx: check for failed allocation lmac->dmacs
From: Colin King @ 2018-08-06 16:50 UTC (permalink / raw)
To: Sunil Goutham, Robert Richter, David S . Miller, linux-arm-kernel,
netdev
Cc: kernel-janitors, linux-kernel
From: Colin Ian King <colin.king@canonical.com>
The allocation of lmac->dmacs is not being checked for allocation
failure. Add the check.
Fixes: 3a34ecfd9d3f ("net: thunderx: add MAC address filter tracking for LMAC")
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index 5d08d2aeb172..e337da6ba2a4 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -1083,6 +1083,8 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
lmac->dmacs_count = (RX_DMAC_COUNT / bgx->lmac_count);
lmac->dmacs = kcalloc(lmac->dmacs_count, sizeof(*lmac->dmacs),
GFP_KERNEL);
+ if (!lmac->dmacs)
+ return -ENOMEM;
/* Enable lmac */
bgx_reg_modify(bgx, lmacid, BGX_CMRX_CFG, CMR_EN);
--
2.17.1
^ permalink raw reply related
* [PATCH net] packet: refine ring v3 block size test to hold one frame
From: Willem de Bruijn @ 2018-08-06 14:38 UTC (permalink / raw)
To: netdev; +Cc: davem, eric.dumazet, loke.chetan, Willem de Bruijn
From: Willem de Bruijn <willemb@google.com>
TPACKET_V3 stores variable length frames in fixed length blocks.
Blocks must be able to store a block header, optional private space
and at least one minimum sized frame.
Frames, even for a zero snaplen packet, store metadata headers and
optional reserved space.
In the block size bounds check, ensure that the frame of the
chosen configuration fits. This includes sockaddr_ll and optional
tp_reserve.
Syzbot was able to construct a ring with insuffient room for the
sockaddr_ll in the header of a zero-length frame, triggering an
out-of-bounds write in dev_parse_header.
Convert the comparison to less than, as zero is a valid snap len.
This matches the test for minimum tp_frame_size immediately below.
Fixes: f6fb8f100b80 ("af-packet: TPACKET_V3 flexible buffer implementation.")
Fixes: eb73190f4fbe ("net/packet: refine check for priv area size")
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Willem de Bruijn <willemb@google.com>
---
net/packet/af_packet.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 9b27d0cd766d5..e6445d8f3f57f 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -4226,6 +4226,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
}
if (req->tp_block_nr) {
+ unsigned int min_frame_size;
+
/* Sanity tests and some calculations */
err = -EBUSY;
if (unlikely(rb->pg_vec))
@@ -4248,12 +4250,12 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
goto out;
if (unlikely(!PAGE_ALIGNED(req->tp_block_size)))
goto out;
+ min_frame_size = po->tp_hdrlen + po->tp_reserve;
if (po->tp_version >= TPACKET_V3 &&
- req->tp_block_size <=
- BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv) + sizeof(struct tpacket3_hdr))
+ req->tp_block_size <
+ BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv) + min_frame_size)
goto out;
- if (unlikely(req->tp_frame_size < po->tp_hdrlen +
- po->tp_reserve))
+ if (unlikely(req->tp_frame_size < min_frame_size))
goto out;
if (unlikely(req->tp_frame_size & (TPACKET_ALIGNMENT - 1)))
goto out;
--
2.18.0.597.ga71716f1ad-goog
^ permalink raw reply related
* [PATCH bpf-next 3/3] bpf: add sample for BPF_MAP_TYPE_QUEUE
From: Mauricio Vasquez B @ 2018-08-06 13:58 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann; +Cc: netdev
In-Reply-To: <153356387977.6981.12236150594041620482.stgit@kernel>
The example is made by two parts, a eBPF program that consumes elements
from a FIFO queue and prints them in the screen and a user space
application that inserts new elements into the queue each time this is
executed.
Signed-off-by: Mauricio Vasquez B <mauricio.vasquez@polito.it>
---
samples/bpf/.gitignore | 1 +
samples/bpf/Makefile | 3 ++
samples/bpf/test_map_in_map_user.c | 9 +-----
samples/bpf/test_queuemap.sh | 37 +++++++++++++++++++++++++
samples/bpf/test_queuemap_kern.c | 51 +++++++++++++++++++++++++++++++++++
samples/bpf/test_queuemap_user.c | 53 ++++++++++++++++++++++++++++++++++++
6 files changed, 147 insertions(+), 7 deletions(-)
create mode 100755 samples/bpf/test_queuemap.sh
create mode 100644 samples/bpf/test_queuemap_kern.c
create mode 100644 samples/bpf/test_queuemap_user.c
diff --git a/samples/bpf/.gitignore b/samples/bpf/.gitignore
index 8ae4940025f8..d7e518c1b3ed 100644
--- a/samples/bpf/.gitignore
+++ b/samples/bpf/.gitignore
@@ -26,6 +26,7 @@ test_lru_dist
test_map_in_map
test_overhead
test_probe_write_user
+test_queuemap
trace_event
trace_output
tracex1
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index f88d5683d6ee..624f4f4b81db 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -53,6 +53,7 @@ hostprogs-y += xdpsock
hostprogs-y += xdp_fwd
hostprogs-y += task_fd_query
hostprogs-y += xdp_sample_pkts
+hostprogs-y += test_queuemap
# Libbpf dependencies
LIBBPF = $(TOOLS_PATH)/lib/bpf/libbpf.a
@@ -109,6 +110,7 @@ xdpsock-objs := xdpsock_user.o
xdp_fwd-objs := xdp_fwd_user.o
task_fd_query-objs := bpf_load.o task_fd_query_user.o $(TRACE_HELPERS)
xdp_sample_pkts-objs := xdp_sample_pkts_user.o $(TRACE_HELPERS)
+test_queuemap-objs := bpf_load.o test_queuemap_user.o
# Tell kbuild to always build the programs
always := $(hostprogs-y)
@@ -166,6 +168,7 @@ always += xdpsock_kern.o
always += xdp_fwd_kern.o
always += task_fd_query_kern.o
always += xdp_sample_pkts_kern.o
+always += test_queuemap_kern.o
HOSTCFLAGS += -I$(objtree)/usr/include
HOSTCFLAGS += -I$(srctree)/tools/lib/
diff --git a/samples/bpf/test_map_in_map_user.c b/samples/bpf/test_map_in_map_user.c
index e308858f7bcf..28edac94234e 100644
--- a/samples/bpf/test_map_in_map_user.c
+++ b/samples/bpf/test_map_in_map_user.c
@@ -1,10 +1,5 @@
-/*
- * Copyright (c) 2017 Facebook
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- */
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018 Politecnico di Torino */
#include <sys/resource.h>
#include <sys/socket.h>
#include <arpa/inet.h>
diff --git a/samples/bpf/test_queuemap.sh b/samples/bpf/test_queuemap.sh
new file mode 100755
index 000000000000..ed08c1fa8c2c
--- /dev/null
+++ b/samples/bpf/test_queuemap.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+[[ -z $TC ]] && TC='tc'
+[[ -z $IP ]] && IP='ip'
+
+TEST_QUEUE_USER='./test_queuemap'
+TEST_QUEUE_BPF='./test_queuemap_kern.o'
+
+function config {
+ $IP netns add ns1
+ $IP link add ve1 type veth peer name vens1
+ $IP link set dev ve1 up
+ $IP link set dev ve1 mtu 1500
+ $IP link set dev vens1 netns ns1
+
+ $IP -n ns1 link set dev lo up
+ $IP -n ns1 link set dev vens1 up
+ $IP -n ns1 addr add 10.1.1.101/24 dev vens1
+
+ $IP addr add 10.1.1.1/24 dev ve1
+ $TC qdisc add dev ve1 clsact
+ $TC filter add dev ve1 ingress bpf da obj $TEST_QUEUE_BPF sec test_queue
+}
+
+function cleanup {
+ set +e
+ [[ -z $DEBUG ]] || set +x
+ $IP netns delete ns1 >& /dev/null
+ $IP link del ve1 >& /dev/null
+ rm -f /sys/fs/bpf/tc/globals/queue
+ [[ -z $DEBUG ]] || set -x
+ set -e
+}
+
+cleanup
+config
diff --git a/samples/bpf/test_queuemap_kern.c b/samples/bpf/test_queuemap_kern.c
new file mode 100644
index 000000000000..2b496dafaffd
--- /dev/null
+++ b/samples/bpf/test_queuemap_kern.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018 Politecnico di Torino */
+#define KBUILD_MODNAME "foo"
+#include <linux/ptrace.h>
+#include <linux/version.h>
+#include <uapi/linux/bpf.h>
+#include <uapi/linux/in6.h>
+#include <uapi/linux/pkt_cls.h>
+#include "bpf_helpers.h"
+
+#define PIN_GLOBAL_NS 2
+
+struct bpf_elf_map {
+ __u32 type;
+ __u32 key_size;
+ __u32 value_size;
+ __u32 max_entries;
+ __u32 flags;
+ __u32 id;
+ __u32 pinning;
+};
+
+/* map #0 */
+struct bpf_elf_map SEC("maps") queue = {
+ .type = BPF_MAP_TYPE_QUEUE,
+ .key_size = 0,
+ .value_size = sizeof(u32),
+ .flags = BPF_F_QUEUE_FIFO,
+ .max_entries = 1024,
+ .pinning = PIN_GLOBAL_NS,
+};
+
+SEC("test_queue")
+int _test_queue(struct __sk_buff *skb)
+{
+ char msg[] = "element is %u\n";
+ char msg_no[] = "there are not elements\n";
+
+ u32 *val = bpf_map_lookup_elem(&queue, NULL);
+
+ if (!val) {
+ bpf_trace_printk(msg_no, sizeof(msg_no));
+ return TC_ACT_OK;
+ }
+
+ bpf_trace_printk(msg, sizeof(msg), *val);
+ return TC_ACT_OK;
+}
+
+char _license[] SEC("license") = "GPL";
+u32 _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/samples/bpf/test_queuemap_user.c b/samples/bpf/test_queuemap_user.c
new file mode 100644
index 000000000000..68f9a5d54596
--- /dev/null
+++ b/samples/bpf/test_queuemap_user.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2018 Politecnico di Torino
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <stdint.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <bpf/bpf.h>
+#include "bpf_load.h"
+
+int queue_map;
+
+static void test_queue_map(void)
+{
+ int ret;
+ uint32_t i;
+
+ queue_map = bpf_obj_get("/sys/fs/bpf/tc/globals/queue");
+ if (queue_map < 0) {
+ fprintf(stderr, "error getting map");
+ return;
+ }
+
+ for (i = 0; i < 256; i++) {
+ uint32_t v = 1000 - i*3;
+
+ ret = bpf_map_update_elem(queue_map, NULL, &v, 0);
+ if (ret)
+ fprintf(stderr, "ret is %d\n", ret);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
+ char filename[256];
+
+ assert(!setrlimit(RLIMIT_MEMLOCK, &r));
+
+ snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
+
+ test_queue_map();
+
+ return 0;
+}
^ permalink raw reply related
* [PATCH bpf-next 2/3] selftests/bpf: add test cases for BPF_MAP_TYPE_QUEUE
From: Mauricio Vasquez B @ 2018-08-06 13:58 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann; +Cc: netdev
In-Reply-To: <153356387977.6981.12236150594041620482.stgit@kernel>
Signed-off-by: Mauricio Vasquez B <mauricio.vasquez@polito.it>
---
tools/include/uapi/linux/bpf.h | 5 ++
tools/testing/selftests/bpf/test_maps.c | 72 +++++++++++++++++++++++++++++++
2 files changed, 77 insertions(+)
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 0ebaaf7f3568..2c171c40eb45 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -120,6 +120,7 @@ enum bpf_map_type {
BPF_MAP_TYPE_CPUMAP,
BPF_MAP_TYPE_XSKMAP,
BPF_MAP_TYPE_SOCKHASH,
+ BPF_MAP_TYPE_QUEUE,
};
enum bpf_prog_type {
@@ -255,6 +256,10 @@ enum bpf_attach_type {
/* Flag for stack_map, store build_id+offset instead of pointer */
#define BPF_F_STACK_BUILD_ID (1U << 5)
+/* Flags for queue_map, type of queue */
+#define BPF_F_QUEUE_FIFO (1U << 16)
+#define BPF_F_QUEUE_LIFO (2U << 16)
+
enum bpf_stack_build_id_status {
/* user space need an empty entry to identify end of a trace */
BPF_STACK_BUILD_ID_EMPTY = 0,
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
index 6c253343a6f9..34567b017dbb 100644
--- a/tools/testing/selftests/bpf/test_maps.c
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -457,6 +457,77 @@ static void test_devmap(int task, void *data)
close(fd);
}
+static void test_queuemap(int task, void *data)
+{
+ __u32 value;
+ int fd, i;
+
+ /* test FIFO */
+ fd = bpf_create_map(BPF_MAP_TYPE_QUEUE, 0, sizeof(value), 32,
+ BPF_F_QUEUE_FIFO);
+ if (fd < 0) {
+ printf("Failed to create queuemap '%s'!\n", strerror(errno));
+ exit(1);
+ }
+
+ /* Push 32 elements */
+ for (i = 0; i < 32; i++) {
+ value = 1000 - i * 3;
+ assert(bpf_map_update_elem(fd, NULL, &value, 0) == 0);
+ }
+
+ /* Check that element cannot be pushed due to max_entries limit */
+ value = 1000;
+ assert(bpf_map_update_elem(fd, NULL, &value, 0) == -1 &&
+ errno == E2BIG);
+
+ /* Pop all elements */
+ for (i = 0; i < 32; i++)
+ assert(bpf_map_lookup_elem(fd, NULL, &value) == 0 &&
+ value == (1000 - i * 3));
+
+ /* Check that there are not elements left */
+ assert(bpf_map_lookup_elem(fd, NULL, &value) == -1 && errno == ENOENT);
+
+ assert(bpf_map_delete_elem(fd, NULL) == -1 && errno == EINVAL);
+ assert(bpf_map_get_next_key(fd, NULL, NULL) == -1 && errno == EINVAL);
+
+ close(fd);
+
+ /* test LIFO */
+ fd = bpf_create_map(BPF_MAP_TYPE_QUEUE, 0, sizeof(value), 32,
+ BPF_F_QUEUE_LIFO);
+ if (fd < 0) {
+ printf("Failed to create queuemap '%s'!\n", strerror(errno));
+ exit(1);
+ }
+
+ /* Push 32 elements */
+ for (i = 0; i < 32; i++) {
+ value = 1000 - i * 3;
+ assert(bpf_map_update_elem(fd, NULL, &value, 0) == 0);
+ }
+
+ /* Check that element cannot be pushed due to max_entries limit */
+ value = 1000;
+ assert(bpf_map_update_elem(fd, NULL, &value, 0) == -1 &&
+ errno == E2BIG);
+
+ /* Pop all elements */
+ for (i = 31; i >= 0; i--)
+ assert(bpf_map_lookup_elem(fd, NULL, &value) == 0 &&
+ value == (1000 - i * 3));
+
+ /* Check that there are not elements left */
+ assert(bpf_map_lookup_elem(fd, NULL, &value) == -1 &&
+ errno == ENOENT);
+
+ assert(bpf_map_delete_elem(fd, NULL) == -1 && errno == EINVAL);
+ assert(bpf_map_get_next_key(fd, NULL, NULL) == -1 && errno == EINVAL);
+
+ close(fd);
+}
+
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
@@ -1162,6 +1233,7 @@ static void run_all_tests(void)
test_arraymap_percpu_many_keys();
test_devmap(0, NULL);
+ test_queuemap(0, NULL);
test_sockmap(0, NULL);
test_map_large();
^ permalink raw reply related
* [PATCH bpf-next 1/3] bpf: add bpf queue map
From: Mauricio Vasquez B @ 2018-08-06 13:58 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann; +Cc: netdev
In-Reply-To: <153356387977.6981.12236150594041620482.stgit@kernel>
Bpf queue implements a LIFO/FIFO data containers for ebpf programs.
It allows to push an element to the queue by using the update operation
and to pop an element from the queue by using the lookup operation.
A use case for this is to keep track of a pool of elements, like
network ports in a SNAT.
Signed-off-by: Mauricio Vasquez B <mauricio.vasquez@polito.it>
---
include/linux/bpf_types.h | 1
include/uapi/linux/bpf.h | 5 +
kernel/bpf/Makefile | 2
kernel/bpf/queuemap.c | 287 +++++++++++++++++++++++++++++++++++++++++++++
kernel/bpf/syscall.c | 61 +++++++---
kernel/bpf/verifier.c | 16 ++-
6 files changed, 353 insertions(+), 19 deletions(-)
create mode 100644 kernel/bpf/queuemap.c
diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h
index c5700c2d5549..6c7a62f3fe43 100644
--- a/include/linux/bpf_types.h
+++ b/include/linux/bpf_types.h
@@ -58,3 +58,4 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_CPUMAP, cpu_map_ops)
BPF_MAP_TYPE(BPF_MAP_TYPE_XSKMAP, xsk_map_ops)
#endif
#endif
+BPF_MAP_TYPE(BPF_MAP_TYPE_QUEUE, queue_map_ops)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 0ebaaf7f3568..2c171c40eb45 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -120,6 +120,7 @@ enum bpf_map_type {
BPF_MAP_TYPE_CPUMAP,
BPF_MAP_TYPE_XSKMAP,
BPF_MAP_TYPE_SOCKHASH,
+ BPF_MAP_TYPE_QUEUE,
};
enum bpf_prog_type {
@@ -255,6 +256,10 @@ enum bpf_attach_type {
/* Flag for stack_map, store build_id+offset instead of pointer */
#define BPF_F_STACK_BUILD_ID (1U << 5)
+/* Flags for queue_map, type of queue */
+#define BPF_F_QUEUE_FIFO (1U << 16)
+#define BPF_F_QUEUE_LIFO (2U << 16)
+
enum bpf_stack_build_id_status {
/* user space need an empty entry to identify end of a trace */
BPF_STACK_BUILD_ID_EMPTY = 0,
diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile
index f27f5496d6fe..30f02ef66635 100644
--- a/kernel/bpf/Makefile
+++ b/kernel/bpf/Makefile
@@ -2,7 +2,7 @@
obj-y := core.o
obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o
-obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o lpm_trie.o map_in_map.o
+obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o lpm_trie.o map_in_map.o queuemap.o
obj-$(CONFIG_BPF_SYSCALL) += disasm.o
obj-$(CONFIG_BPF_SYSCALL) += btf.o
ifeq ($(CONFIG_NET),y)
diff --git a/kernel/bpf/queuemap.c b/kernel/bpf/queuemap.c
new file mode 100644
index 000000000000..ab30af43b4cc
--- /dev/null
+++ b/kernel/bpf/queuemap.c
@@ -0,0 +1,287 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * queuemap.c: BPF queue map
+ *
+ * Copyright (c) 2018 Politecnico di Torino
+ */
+#include <linux/bpf.h>
+#include <linux/rculist.h>
+#include <linux/slab.h>
+#include "percpu_freelist.h"
+
+#define QUEUE_CREATE_FLAG_MASK \
+ (BPF_F_NO_PREALLOC | BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY | \
+ BPF_F_QUEUE_FIFO | BPF_F_QUEUE_LIFO)
+
+enum queue_type {
+ QUEUE_FIFO = (BPF_F_QUEUE_FIFO >> 16),
+ QUEUE_LIFO = (BPF_F_QUEUE_LIFO >> 16),
+};
+
+struct bpf_queue {
+ struct bpf_map map;
+ struct list_head head;
+ struct pcpu_freelist freelist;
+ void *nodes;
+ enum queue_type type;
+ raw_spinlock_t lock;
+ atomic_t count;
+ u32 node_size;
+};
+
+struct queue_node {
+ struct pcpu_freelist_node fnode;
+ struct bpf_queue *queue;
+ struct list_head list;
+ struct rcu_head rcu;
+ char element[0] __aligned(8);
+};
+
+static bool queue_map_is_prealloc(struct bpf_queue *queue)
+{
+ return !(queue->map.map_flags & BPF_F_NO_PREALLOC);
+}
+
+/* Called from syscall */
+static int queue_map_alloc_check(union bpf_attr *attr)
+{
+ /* check sanity of attributes */
+ if (attr->max_entries == 0 || attr->key_size != 0 ||
+ attr->value_size == 0 || attr->map_flags & ~QUEUE_CREATE_FLAG_MASK)
+ return -EINVAL;
+
+ if ((attr->map_flags >> 16) != QUEUE_FIFO &&
+ (attr->map_flags >> 16) != QUEUE_LIFO) {
+ return -EINVAL;
+ }
+
+ if (attr->value_size > KMALLOC_MAX_SIZE)
+ /* if value_size is bigger, the user space won't be able to
+ * access the elements.
+ */
+ return -E2BIG;
+
+ return 0;
+}
+
+static int prealloc_init(struct bpf_queue *queue)
+{
+ u32 node_size = sizeof(struct queue_node) +
+ round_up(queue->map.value_size, 8);
+ u32 num_entries = queue->map.max_entries;
+ int err;
+
+ queue->nodes = bpf_map_area_alloc(node_size * num_entries,
+ queue->map.numa_node);
+ if (!queue->nodes)
+ return -ENOMEM;
+
+ err = pcpu_freelist_init(&queue->freelist);
+ if (err)
+ goto free_nodes;
+
+ pcpu_freelist_populate(&queue->freelist,
+ queue->nodes +
+ offsetof(struct queue_node, fnode),
+ node_size, num_entries);
+
+ return 0;
+
+free_nodes:
+ bpf_map_area_free(queue->nodes);
+ return err;
+}
+
+static void prealloc_destroy(struct bpf_queue *queue)
+{
+ bpf_map_area_free(queue->nodes);
+ pcpu_freelist_destroy(&queue->freelist);
+}
+
+static struct bpf_map *queue_map_alloc(union bpf_attr *attr)
+{
+ struct bpf_queue *queue;
+ u64 cost = sizeof(*queue);
+ int ret;
+
+ queue = kzalloc(sizeof(*queue), GFP_USER);
+ if (!queue)
+ return ERR_PTR(-ENOMEM);
+
+ bpf_map_init_from_attr(&queue->map, attr);
+
+ queue->node_size = sizeof(struct queue_node) +
+ round_up(attr->value_size, 8);
+ cost += (u64) attr->max_entries * queue->node_size;
+ if (cost >= U32_MAX - PAGE_SIZE) {
+ ret = -E2BIG;
+ goto free_queue;
+ }
+
+ queue->map.pages = round_up(cost, PAGE_SIZE) >> PAGE_SHIFT;
+
+ ret = bpf_map_precharge_memlock(queue->map.pages);
+ if (ret)
+ goto free_queue;
+
+ INIT_LIST_HEAD(&queue->head);
+
+ raw_spin_lock_init(&queue->lock);
+
+ queue->type = attr->map_flags >> 16;
+
+ if (queue_map_is_prealloc(queue))
+ ret = prealloc_init(queue);
+ if (ret)
+ goto free_queue;
+
+ return &queue->map;
+
+free_queue:
+ kfree(queue);
+ return ERR_PTR(ret);
+}
+
+/* Called when map->refcnt goes to zero, either from workqueue or from syscall */
+static void queue_map_free(struct bpf_map *map)
+{
+ struct bpf_queue *queue = container_of(map, struct bpf_queue, map);
+ struct queue_node *l;
+
+ /* at this point bpf_prog->aux->refcnt == 0 and this map->refcnt == 0,
+ * so the programs (can be more than one that used this map) were
+ * disconnected from events. Wait for outstanding critical sections in
+ * these programs to complete
+ */
+ synchronize_rcu();
+
+ /* some of queue_elem_free_rcu() callbacks for elements of this map may
+ * not have executed. Wait for them.
+ */
+ rcu_barrier();
+ if (!queue_map_is_prealloc(queue))
+ list_for_each_entry_rcu(l, &queue->head, list) {
+ list_del_rcu(&l->list);
+ kfree(l);
+ }
+ else
+ prealloc_destroy(queue);
+ kfree(queue);
+}
+
+static void queue_elem_free_rcu(struct rcu_head *head)
+{
+ struct queue_node *l = container_of(head, struct queue_node, rcu);
+ struct bpf_queue *queue = l->queue;
+
+ /* must increment bpf_prog_active to avoid kprobe+bpf triggering while
+ * we're calling kfree, otherwise deadlock is possible if kprobes
+ * are placed somewhere inside of slub
+ */
+ preempt_disable();
+ __this_cpu_inc(bpf_prog_active);
+ if (queue_map_is_prealloc(queue))
+ pcpu_freelist_push(&queue->freelist, &l->fnode);
+ else
+ kfree(l);
+ __this_cpu_dec(bpf_prog_active);
+ preempt_enable();
+}
+
+/* Called from syscall or from eBPF program */
+static void *queue_map_lookup_elem(struct bpf_map *map, void *key)
+{
+ struct bpf_queue *queue = container_of(map, struct bpf_queue, map);
+ unsigned long flags;
+ struct queue_node *node;
+
+ raw_spin_lock_irqsave(&queue->lock, flags);
+
+ node = list_first_or_null_rcu(&queue->head, struct queue_node, list);
+ if (!node) {
+ raw_spin_unlock_irqrestore(&queue->lock, flags);
+ return NULL;
+ }
+
+ if (!queue_map_is_prealloc(queue))
+ atomic_dec(&queue->count);
+
+ list_del_rcu(&node->list);
+ call_rcu(&node->rcu, queue_elem_free_rcu);
+
+ raw_spin_unlock_irqrestore(&queue->lock, flags);
+
+ return &node->element;
+}
+
+/* Called from syscall or from eBPF program */
+static int queue_map_update_elem(struct bpf_map *map, void *key, void *value,
+ u64 map_flags)
+{
+ struct bpf_queue *queue = container_of(map, struct bpf_queue, map);
+ unsigned long flags;
+ struct queue_node *new;
+
+ if (!queue_map_is_prealloc(queue)) {
+ if (atomic_inc_return(&queue->count) > queue->map.max_entries) {
+ atomic_dec(&queue->count);
+ return -E2BIG;
+ }
+
+ new = kmalloc_node(queue->node_size, GFP_ATOMIC | __GFP_NOWARN,
+ queue->map.numa_node);
+ if (!new) {
+ atomic_dec(&queue->count);
+ return -ENOMEM;
+ }
+ } else {
+ struct pcpu_freelist_node *l;
+
+ l = pcpu_freelist_pop(&queue->freelist);
+ if (!l)
+ return -E2BIG;
+ new = container_of(l, struct queue_node, fnode);
+ }
+
+ memcpy(new->element, value, queue->map.value_size);
+ new->queue = queue;
+
+ raw_spin_lock_irqsave(&queue->lock, flags);
+ switch (queue->type) {
+ case QUEUE_FIFO:
+ list_add_tail_rcu(&new->list, &queue->head);
+ break;
+
+ case QUEUE_LIFO:
+ list_add_rcu(&new->list, &queue->head);
+ break;
+ }
+
+ raw_spin_unlock_irqrestore(&queue->lock, flags);
+
+ return 0;
+}
+
+/* Called from syscall or from eBPF program */
+static int queue_map_delete_elem(struct bpf_map *map, void *key)
+{
+ return -EINVAL;
+}
+
+/* Called from syscall */
+static int queue_map_get_next_key(struct bpf_map *map, void *key,
+ void *next_key)
+{
+ return -EINVAL;
+}
+
+const struct bpf_map_ops queue_map_ops = {
+ .map_alloc_check = queue_map_alloc_check,
+ .map_alloc = queue_map_alloc,
+ .map_free = queue_map_free,
+ .map_lookup_elem = queue_map_lookup_elem,
+ .map_update_elem = queue_map_update_elem,
+ .map_delete_elem = queue_map_delete_elem,
+ .map_get_next_key = queue_map_get_next_key,
+};
+
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index a31a1ba0f8ea..7e9a11d69eef 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -622,11 +622,19 @@ static int map_lookup_elem(union bpf_attr *attr)
err = -EPERM;
goto err_put;
}
+ if (map->map_type != BPF_MAP_TYPE_QUEUE) {
+ key = memdup_user(ukey, map->key_size);
+ if (IS_ERR(key)) {
+ err = PTR_ERR(key);
+ goto err_put;
+ }
+ } else {
+ if (ukey) {
+ err = -EINVAL;
+ goto err_put;
+ }
- key = memdup_user(ukey, map->key_size);
- if (IS_ERR(key)) {
- err = PTR_ERR(key);
- goto err_put;
+ key = NULL;
}
if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
@@ -709,10 +717,19 @@ static int map_update_elem(union bpf_attr *attr)
goto err_put;
}
- key = memdup_user(ukey, map->key_size);
- if (IS_ERR(key)) {
- err = PTR_ERR(key);
- goto err_put;
+ if (map->map_type != BPF_MAP_TYPE_QUEUE) {
+ key = memdup_user(ukey, map->key_size);
+ if (IS_ERR(key)) {
+ err = PTR_ERR(key);
+ goto err_put;
+ }
+ } else {
+ if (ukey) {
+ err = -EINVAL;
+ goto err_put;
+ }
+
+ key = NULL;
}
if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
@@ -803,10 +820,19 @@ static int map_delete_elem(union bpf_attr *attr)
goto err_put;
}
- key = memdup_user(ukey, map->key_size);
- if (IS_ERR(key)) {
- err = PTR_ERR(key);
- goto err_put;
+ if (map->map_type != BPF_MAP_TYPE_QUEUE) {
+ key = memdup_user(ukey, map->key_size);
+ if (IS_ERR(key)) {
+ err = PTR_ERR(key);
+ goto err_put;
+ }
+ } else {
+ if (ukey) {
+ err = -EINVAL;
+ goto err_put;
+ }
+
+ key = NULL;
}
if (bpf_map_is_dev_bound(map)) {
@@ -855,9 +881,14 @@ static int map_get_next_key(union bpf_attr *attr)
}
if (ukey) {
- key = memdup_user(ukey, map->key_size);
- if (IS_ERR(key)) {
- err = PTR_ERR(key);
+ if (map->map_type != BPF_MAP_TYPE_QUEUE) {
+ key = memdup_user(ukey, map->key_size);
+ if (IS_ERR(key)) {
+ err = PTR_ERR(key);
+ goto err_put;
+ }
+ } else {
+ err = -EINVAL;
goto err_put;
}
} else {
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 25e47c195874..83099a9a21d9 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1976,8 +1976,12 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
return -EACCES;
}
- if (arg_type == ARG_PTR_TO_MAP_KEY ||
- arg_type == ARG_PTR_TO_MAP_VALUE) {
+ if (arg_type == ARG_PTR_TO_MAP_KEY) {
+ expected_type = PTR_TO_STACK;
+ if (!type_is_pkt_pointer(type) && type != PTR_TO_MAP_VALUE &&
+ type != expected_type && type != SCALAR_VALUE)
+ goto err_type;
+ } else if (arg_type == ARG_PTR_TO_MAP_VALUE) {
expected_type = PTR_TO_STACK;
if (!type_is_pkt_pointer(type) && type != PTR_TO_MAP_VALUE &&
type != expected_type)
@@ -2021,6 +2025,7 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
/* bpf_map_xxx(map_ptr) call: remember that map_ptr */
meta->map_ptr = reg->map_ptr;
} else if (arg_type == ARG_PTR_TO_MAP_KEY) {
+ bool zero_size_allowed = false;
/* bpf_map_xxx(..., map_ptr, ..., key) call:
* check that [key, key + map->key_size) are within
* stack limits and initialized
@@ -2034,8 +2039,13 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
verbose(env, "invalid map_ptr to access map->key\n");
return -EACCES;
}
+
+ if (meta->map_ptr->map_type == BPF_MAP_TYPE_QUEUE)
+ zero_size_allowed = true;
+
err = check_helper_mem_access(env, regno,
- meta->map_ptr->key_size, false,
+ meta->map_ptr->key_size,
+ zero_size_allowed,
NULL);
} else if (arg_type == ARG_PTR_TO_MAP_VALUE) {
/* bpf_map_xxx(..., map_ptr, ..., value) call:
^ permalink raw reply related
* [PATCH bpf-next 0/3] Implement bpf map queue
From: Mauricio Vasquez B @ 2018-08-06 13:58 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann; +Cc: netdev
Bpf queue map is a new kind of map that provides a LIFO/FIFO queue
implementation.
In some applications, like a SNAT, it is necessary to keep track of
a pool of free elemenets, network ports in this case, then a queue
can be used for that purpose.
Signed-off-by: Mauricio Vasquez B <mauricio.vasquez@polito.it>
---
Mauricio Vasquez B (3):
bpf: add bpf queue map
selftests/bpf: add test cases for BPF_MAP_TYPE_QUEUE
bpf: add sample for BPF_MAP_TYPE_QUEUE
include/linux/bpf_types.h | 1
include/uapi/linux/bpf.h | 5 +
kernel/bpf/Makefile | 2
kernel/bpf/queuemap.c | 287 +++++++++++++++++++++++++++++++
kernel/bpf/syscall.c | 61 +++++--
kernel/bpf/verifier.c | 16 +-
samples/bpf/.gitignore | 1
samples/bpf/Makefile | 3
samples/bpf/test_map_in_map_user.c | 9 -
samples/bpf/test_queuemap.sh | 37 ++++
samples/bpf/test_queuemap_kern.c | 51 ++++++
samples/bpf/test_queuemap_user.c | 53 ++++++
tools/include/uapi/linux/bpf.h | 5 +
tools/testing/selftests/bpf/test_maps.c | 72 ++++++++
14 files changed, 577 insertions(+), 26 deletions(-)
create mode 100644 kernel/bpf/queuemap.c
create mode 100755 samples/bpf/test_queuemap.sh
create mode 100644 samples/bpf/test_queuemap_kern.c
create mode 100644 samples/bpf/test_queuemap_user.c
^ permalink raw reply
* Re: [PATCH] Use Kconfig flag to remove support of deprecated BE2/BE3 adapters
From: Christoph Hellwig @ 2018-08-06 16:21 UTC (permalink / raw)
To: Petr Oros
Cc: netdev, ivecera, Sathya Perla, Ajit Khaparde,
Sriharsha Basavapatna, Somnath Kotur, David S. Miller,
linux-kernel
In-Reply-To: <20180806121230.23690-1-poros@redhat.com>
On Mon, Aug 06, 2018 at 02:12:28PM +0200, Petr Oros wrote:
> Add flags to remove support of deprecated BE2/BE3 adapters.
> BE2 disable will reduce .ko size by 2kb and BE3 by 3kb.
> Disable both will reduce .ko size by 9kb.
>
> With dissabled support is also removed coresponding PCI IDs
> and codepath with [BE2|BE3|BEx]_chip checks.
deprecated seems like a really odd world for hardware.
Are they just old? Did they never ship in large numbers?
If you just make some cards optional why not also add options
for families of newer cards for those who only have the older ones
in their systems?
^ permalink raw reply
* [PATCH v3] can: sja1000: plx_pci: add support for ASEM CAN raw device
From: Flavio Suligoi @ 2018-08-06 14:11 UTC (permalink / raw)
To: Wolfgang Grandegger, Marc Kleine-Budde
Cc: David S . Miller, linux-can, netdev, linux-kernel, Flavio Suligoi
In-Reply-To: <ac6e38c7-f794-6efd-4942-9b2a3fa7a0d0@pengutronix.de>
This patch adds support for ASEM opto-isolated dual channels
CAN raw device (http://www.asem.it)
Signed-off-by: Flavio Suligoi <f.suligoi@asem.it>
---
v2: - rename ASEM_... constants to reduce space size;
- remove "else" in "plx_pci_reset_asem_dual_can_raw" function to avoid
strings breaking
v3: - fix wrong comment for PLX_LINT2_POL
- put string into just one line in "plx_pci_reset_asem_dual_can_raw"
function
drivers/net/can/sja1000/Kconfig | 1 +
drivers/net/can/sja1000/plx_pci.c | 67 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig
index 1e65cb6..f6dc899 100644
--- a/drivers/net/can/sja1000/Kconfig
+++ b/drivers/net/can/sja1000/Kconfig
@@ -88,6 +88,7 @@ config CAN_PLX_PCI
- TEWS TECHNOLOGIES TPMC810 card (http://www.tews.com/)
- IXXAT Automation PC-I 04/PCI card (http://www.ixxat.com/)
- Connect Tech Inc. CANpro/104-Plus Opto (CRG001) card (http://www.connecttech.com)
+ - ASEM CAN raw - 2 isolated CAN channels (www.asem.it)
config CAN_TSCAN1
tristate "TS-CAN1 PC104 boards"
diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c
index f8ff25c..f3915db 100644
--- a/drivers/net/can/sja1000/plx_pci.c
+++ b/drivers/net/can/sja1000/plx_pci.c
@@ -46,7 +46,8 @@ MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, "
"esd CAN-PCIe/2000, "
"Connect Tech Inc. CANpro/104-Plus Opto (CRG001), "
"IXXAT PC-I 04/PCI, "
- "ELCUS CAN-200-PCI")
+ "ELCUS CAN-200-PCI, "
+ "ASEM DUAL CAN-RAW")
MODULE_LICENSE("GPL v2");
#define PLX_PCI_MAX_CHAN 2
@@ -70,7 +71,9 @@ struct plx_pci_card {
*/
#define PLX_LINT1_EN 0x1 /* Local interrupt 1 enable */
+#define PLX_LINT1_POL (1 << 1) /* Local interrupt 1 polarity */
#define PLX_LINT2_EN (1 << 3) /* Local interrupt 2 enable */
+#define PLX_LINT2_POL (1 << 4) /* Local interrupt 2 polarity */
#define PLX_PCI_INT_EN (1 << 6) /* PCI Interrupt Enable */
#define PLX_PCI_RESET (1 << 30) /* PCI Adapter Software Reset */
@@ -92,6 +95,9 @@ struct plx_pci_card {
*/
#define PLX_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL)
+/* OCR setting for ASEM Dual CAN raw */
+#define ASEM_PCI_OCR 0xfe
+
/*
* In the CDR register, you should set CBP to 1.
* You will probably also want to set the clock divider value to 7
@@ -145,10 +151,20 @@ struct plx_pci_card {
#define MOXA_PCI_VENDOR_ID 0x1393
#define MOXA_PCI_DEVICE_ID 0x0100
+#define ASEM_RAW_CAN_VENDOR_ID 0x10b5
+#define ASEM_RAW_CAN_DEVICE_ID 0x9030
+#define ASEM_RAW_CAN_SUB_VENDOR_ID 0x3000
+#define ASEM_RAW_CAN_SUB_DEVICE_ID 0x1001
+#define ASEM_RAW_CAN_SUB_DEVICE_ID_BIS 0x1002
+#define ASEM_RAW_CAN_RST_REGISTER 0x54
+#define ASEM_RAW_CAN_RST_MASK_CAN1 0x20
+#define ASEM_RAW_CAN_RST_MASK_CAN2 0x04
+
static void plx_pci_reset_common(struct pci_dev *pdev);
static void plx9056_pci_reset_common(struct pci_dev *pdev);
static void plx_pci_reset_marathon_pci(struct pci_dev *pdev);
static void plx_pci_reset_marathon_pcie(struct pci_dev *pdev);
+static void plx_pci_reset_asem_dual_can_raw(struct pci_dev *pdev);
struct plx_pci_channel_map {
u32 bar;
@@ -269,6 +285,14 @@ static struct plx_pci_card_info plx_pci_card_info_moxa = {
/* based on PLX9052 */
};
+static struct plx_pci_card_info plx_pci_card_info_asem_dual_can = {
+ "ASEM Dual CAN raw PCI", 2,
+ PLX_PCI_CAN_CLOCK, ASEM_PCI_OCR, PLX_PCI_CDR,
+ {0, 0x00, 0x00}, { {2, 0x00, 0x00}, {4, 0x00, 0x00} },
+ &plx_pci_reset_asem_dual_can_raw
+ /* based on PLX9030 */
+};
+
static const struct pci_device_id plx_pci_tbl[] = {
{
/* Adlink PCI-7841/cPCI-7841 */
@@ -375,6 +399,20 @@ static const struct pci_device_id plx_pci_tbl[] = {
0, 0,
(kernel_ulong_t)&plx_pci_card_info_moxa
},
+ {
+ /* ASEM Dual CAN raw */
+ ASEM_RAW_CAN_VENDOR_ID, ASEM_RAW_CAN_DEVICE_ID,
+ ASEM_RAW_CAN_SUB_VENDOR_ID, ASEM_RAW_CAN_SUB_DEVICE_ID,
+ 0, 0,
+ (kernel_ulong_t)&plx_pci_card_info_asem_dual_can
+ },
+ {
+ /* ASEM Dual CAN raw -new model */
+ ASEM_RAW_CAN_VENDOR_ID, ASEM_RAW_CAN_DEVICE_ID,
+ ASEM_RAW_CAN_SUB_VENDOR_ID, ASEM_RAW_CAN_SUB_DEVICE_ID_BIS,
+ 0, 0,
+ (kernel_ulong_t)&plx_pci_card_info_asem_dual_can
+ },
{ 0,}
};
MODULE_DEVICE_TABLE(pci, plx_pci_tbl);
@@ -524,6 +562,33 @@ static void plx_pci_reset_marathon_pcie(struct pci_dev *pdev)
}
}
+/* Special reset function for ASEM Dual CAN raw card */
+static void plx_pci_reset_asem_dual_can_raw(struct pci_dev *pdev)
+{
+ void __iomem *bar0_addr;
+ static const int reset_bar;
+ u8 tmpval;
+
+ plx_pci_reset_common(pdev);
+
+ bar0_addr = pci_iomap(pdev, reset_bar, 0);
+ if (!bar0_addr) {
+ dev_err(&pdev->dev, "Failed to remap reset space %d (BAR%d)\n",
+ 0, reset_bar);
+ return;
+ }
+
+ /* reset the two SJA1000 chips */
+ tmpval = ioread8(bar0_addr + ASEM_RAW_CAN_RST_REGISTER);
+ tmpval &= ~(ASEM_RAW_CAN_RST_MASK_CAN1 | ASEM_RAW_CAN_RST_MASK_CAN2);
+ iowrite8(tmpval, bar0_addr + ASEM_RAW_CAN_RST_REGISTER);
+ usleep_range(300, 400);
+ tmpval |= ASEM_RAW_CAN_RST_MASK_CAN1 | ASEM_RAW_CAN_RST_MASK_CAN2;
+ iowrite8(tmpval, bar0_addr + ASEM_RAW_CAN_RST_REGISTER);
+ usleep_range(300, 400);
+ pci_iounmap(pdev, bar0_addr);
+}
+
static void plx_pci_del_card(struct pci_dev *pdev)
{
struct plx_pci_card *card = pci_get_drvdata(pdev);
--
2.7.4
^ permalink raw reply related
* Re: [PATCH v3] can: sja1000: plx_pci: add support for ASEM CAN raw device
From: Marc Kleine-Budde @ 2018-08-06 16:07 UTC (permalink / raw)
To: Flavio Suligoi, Wolfgang Grandegger
Cc: David S . Miller, linux-can, netdev, linux-kernel
In-Reply-To: <1533564703-32194-1-git-send-email-f.suligoi@asem.it>
[-- Attachment #1.1: Type: text/plain, Size: 6195 bytes --]
On 08/06/2018 04:11 PM, Flavio Suligoi wrote:
> This patch adds support for ASEM opto-isolated dual channels
> CAN raw device (http://www.asem.it)
>
> Signed-off-by: Flavio Suligoi <f.suligoi@asem.it>
> ---
>
> v2: - rename ASEM_... constants to reduce space size;
> - remove "else" in "plx_pci_reset_asem_dual_can_raw" function to avoid
> strings breaking
> v3: - fix wrong comment for PLX_LINT2_POL
> - put string into just one line in "plx_pci_reset_asem_dual_can_raw"
> function
>
> drivers/net/can/sja1000/Kconfig | 1 +
> drivers/net/can/sja1000/plx_pci.c | 67 ++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 67 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig
> index 1e65cb6..f6dc899 100644
> --- a/drivers/net/can/sja1000/Kconfig
> +++ b/drivers/net/can/sja1000/Kconfig
> @@ -88,6 +88,7 @@ config CAN_PLX_PCI
> - TEWS TECHNOLOGIES TPMC810 card (http://www.tews.com/)
> - IXXAT Automation PC-I 04/PCI card (http://www.ixxat.com/)
> - Connect Tech Inc. CANpro/104-Plus Opto (CRG001) card (http://www.connecttech.com)
> + - ASEM CAN raw - 2 isolated CAN channels (www.asem.it)
>
> config CAN_TSCAN1
> tristate "TS-CAN1 PC104 boards"
> diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c
> index f8ff25c..f3915db 100644
> --- a/drivers/net/can/sja1000/plx_pci.c
> +++ b/drivers/net/can/sja1000/plx_pci.c
> @@ -46,7 +46,8 @@ MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, "
> "esd CAN-PCIe/2000, "
> "Connect Tech Inc. CANpro/104-Plus Opto (CRG001), "
> "IXXAT PC-I 04/PCI, "
> - "ELCUS CAN-200-PCI")
> + "ELCUS CAN-200-PCI, "
> + "ASEM DUAL CAN-RAW")
> MODULE_LICENSE("GPL v2");
>
> #define PLX_PCI_MAX_CHAN 2
> @@ -70,7 +71,9 @@ struct plx_pci_card {
> */
>
> #define PLX_LINT1_EN 0x1 /* Local interrupt 1 enable */
> +#define PLX_LINT1_POL (1 << 1) /* Local interrupt 1 polarity */
> #define PLX_LINT2_EN (1 << 3) /* Local interrupt 2 enable */
> +#define PLX_LINT2_POL (1 << 4) /* Local interrupt 2 polarity */
> #define PLX_PCI_INT_EN (1 << 6) /* PCI Interrupt Enable */
> #define PLX_PCI_RESET (1 << 30) /* PCI Adapter Software Reset */
>
> @@ -92,6 +95,9 @@ struct plx_pci_card {
> */
> #define PLX_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL)
>
> +/* OCR setting for ASEM Dual CAN raw */
> +#define ASEM_PCI_OCR 0xfe
> +
> /*
> * In the CDR register, you should set CBP to 1.
> * You will probably also want to set the clock divider value to 7
> @@ -145,10 +151,20 @@ struct plx_pci_card {
> #define MOXA_PCI_VENDOR_ID 0x1393
> #define MOXA_PCI_DEVICE_ID 0x0100
>
> +#define ASEM_RAW_CAN_VENDOR_ID 0x10b5
> +#define ASEM_RAW_CAN_DEVICE_ID 0x9030
> +#define ASEM_RAW_CAN_SUB_VENDOR_ID 0x3000
> +#define ASEM_RAW_CAN_SUB_DEVICE_ID 0x1001
> +#define ASEM_RAW_CAN_SUB_DEVICE_ID_BIS 0x1002
> +#define ASEM_RAW_CAN_RST_REGISTER 0x54
> +#define ASEM_RAW_CAN_RST_MASK_CAN1 0x20
> +#define ASEM_RAW_CAN_RST_MASK_CAN2 0x04
> +
> static void plx_pci_reset_common(struct pci_dev *pdev);
> static void plx9056_pci_reset_common(struct pci_dev *pdev);
> static void plx_pci_reset_marathon_pci(struct pci_dev *pdev);
> static void plx_pci_reset_marathon_pcie(struct pci_dev *pdev);
> +static void plx_pci_reset_asem_dual_can_raw(struct pci_dev *pdev);
>
> struct plx_pci_channel_map {
> u32 bar;
> @@ -269,6 +285,14 @@ static struct plx_pci_card_info plx_pci_card_info_moxa = {
> /* based on PLX9052 */
> };
>
> +static struct plx_pci_card_info plx_pci_card_info_asem_dual_can = {
> + "ASEM Dual CAN raw PCI", 2,
> + PLX_PCI_CAN_CLOCK, ASEM_PCI_OCR, PLX_PCI_CDR,
> + {0, 0x00, 0x00}, { {2, 0x00, 0x00}, {4, 0x00, 0x00} },
> + &plx_pci_reset_asem_dual_can_raw
> + /* based on PLX9030 */
> +};
> +
> static const struct pci_device_id plx_pci_tbl[] = {
> {
> /* Adlink PCI-7841/cPCI-7841 */
> @@ -375,6 +399,20 @@ static const struct pci_device_id plx_pci_tbl[] = {
> 0, 0,
> (kernel_ulong_t)&plx_pci_card_info_moxa
> },
> + {
> + /* ASEM Dual CAN raw */
> + ASEM_RAW_CAN_VENDOR_ID, ASEM_RAW_CAN_DEVICE_ID,
> + ASEM_RAW_CAN_SUB_VENDOR_ID, ASEM_RAW_CAN_SUB_DEVICE_ID,
> + 0, 0,
> + (kernel_ulong_t)&plx_pci_card_info_asem_dual_can
> + },
> + {
> + /* ASEM Dual CAN raw -new model */
> + ASEM_RAW_CAN_VENDOR_ID, ASEM_RAW_CAN_DEVICE_ID,
> + ASEM_RAW_CAN_SUB_VENDOR_ID, ASEM_RAW_CAN_SUB_DEVICE_ID_BIS,
> + 0, 0,
> + (kernel_ulong_t)&plx_pci_card_info_asem_dual_can
> + },
> { 0,}
> };
> MODULE_DEVICE_TABLE(pci, plx_pci_tbl);
> @@ -524,6 +562,33 @@ static void plx_pci_reset_marathon_pcie(struct pci_dev *pdev)
> }
> }
>
> +/* Special reset function for ASEM Dual CAN raw card */
> +static void plx_pci_reset_asem_dual_can_raw(struct pci_dev *pdev)
> +{
> + void __iomem *bar0_addr;
> + static const int reset_bar;
> + u8 tmpval;
> +
> + plx_pci_reset_common(pdev);
> +
> + bar0_addr = pci_iomap(pdev, reset_bar, 0);
We can just use '0' instead of 'reset_bar' here, right?
Marc
> + if (!bar0_addr) {
> + dev_err(&pdev->dev, "Failed to remap reset space %d (BAR%d)\n",
> + 0, reset_bar);
> + return;
> + }
> +
> + /* reset the two SJA1000 chips */
> + tmpval = ioread8(bar0_addr + ASEM_RAW_CAN_RST_REGISTER);
> + tmpval &= ~(ASEM_RAW_CAN_RST_MASK_CAN1 | ASEM_RAW_CAN_RST_MASK_CAN2);
> + iowrite8(tmpval, bar0_addr + ASEM_RAW_CAN_RST_REGISTER);
> + usleep_range(300, 400);
> + tmpval |= ASEM_RAW_CAN_RST_MASK_CAN1 | ASEM_RAW_CAN_RST_MASK_CAN2;
> + iowrite8(tmpval, bar0_addr + ASEM_RAW_CAN_RST_REGISTER);
> + usleep_range(300, 400);
> + pci_iounmap(pdev, bar0_addr);
> +}
> +
> static void plx_pci_del_card(struct pci_dev *pdev)
> {
> struct plx_pci_card *card = pci_get_drvdata(pdev);
>
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH v2] can: sja1000: plx_pci: add support for ASEM CAN raw device
From: Marc Kleine-Budde @ 2018-08-06 13:49 UTC (permalink / raw)
To: Flavio Suligoi, Wolfgang Grandegger
Cc: David S . Miller, linux-can, netdev, linux-kernel
In-Reply-To: <1533561432-27034-1-git-send-email-f.suligoi@asem.it>
[-- Attachment #1.1: Type: text/plain, Size: 6120 bytes --]
On 08/06/2018 03:17 PM, Flavio Suligoi wrote:
> This patch adds support for ASEM opto-isolated dual channels
> CAN raw device (http://www.asem.it)
>
> Signed-off-by: Flavio Suligoi <f.suligoi@asem.it>
> ---
>
> v2: - renamed ASEM_... constants to reduce space size;
> - remove "else" in "plx_pci_reset_asem_dual_can_raw" function to avoid
> strings breaking
>
> drivers/net/can/sja1000/Kconfig | 1 +
> drivers/net/can/sja1000/plx_pci.c | 67 ++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 67 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig
> index 1e65cb6..f6dc899 100644
> --- a/drivers/net/can/sja1000/Kconfig
> +++ b/drivers/net/can/sja1000/Kconfig
> @@ -88,6 +88,7 @@ config CAN_PLX_PCI
> - TEWS TECHNOLOGIES TPMC810 card (http://www.tews.com/)
> - IXXAT Automation PC-I 04/PCI card (http://www.ixxat.com/)
> - Connect Tech Inc. CANpro/104-Plus Opto (CRG001) card (http://www.connecttech.com)
> + - ASEM CAN raw - 2 isolated CAN channels (www.asem.it)
>
> config CAN_TSCAN1
> tristate "TS-CAN1 PC104 boards"
> diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c
> index f8ff25c..d8dfa06 100644
> --- a/drivers/net/can/sja1000/plx_pci.c
> +++ b/drivers/net/can/sja1000/plx_pci.c
> @@ -46,7 +46,8 @@ MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, "
> "esd CAN-PCIe/2000, "
> "Connect Tech Inc. CANpro/104-Plus Opto (CRG001), "
> "IXXAT PC-I 04/PCI, "
> - "ELCUS CAN-200-PCI")
> + "ELCUS CAN-200-PCI, "
> + "ASEM DUAL CAN-RAW")
> MODULE_LICENSE("GPL v2");
>
> #define PLX_PCI_MAX_CHAN 2
> @@ -70,7 +71,9 @@ struct plx_pci_card {
> */
>
> #define PLX_LINT1_EN 0x1 /* Local interrupt 1 enable */
> +#define PLX_LINT1_POL (1 << 1) /* Local interrupt 1 polarity */
> #define PLX_LINT2_EN (1 << 3) /* Local interrupt 2 enable */
> +#define PLX_LINT2_POL (1 << 4) /* Local interrupt 1 polarity */
^^^
2?
> #define PLX_PCI_INT_EN (1 << 6) /* PCI Interrupt Enable */
> #define PLX_PCI_RESET (1 << 30) /* PCI Adapter Software Reset */
>
> @@ -92,6 +95,9 @@ struct plx_pci_card {
> */
> #define PLX_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL)
>
> +/* OCR setting for ASEM Dual CAN raw */
> +#define ASEM_PCI_OCR 0xfe
> +
> /*
> * In the CDR register, you should set CBP to 1.
> * You will probably also want to set the clock divider value to 7
> @@ -145,10 +151,20 @@ struct plx_pci_card {
> #define MOXA_PCI_VENDOR_ID 0x1393
> #define MOXA_PCI_DEVICE_ID 0x0100
>
> +#define ASEM_RAW_CAN_VENDOR_ID 0x10b5
> +#define ASEM_RAW_CAN_DEVICE_ID 0x9030
> +#define ASEM_RAW_CAN_SUB_VENDOR_ID 0x3000
> +#define ASEM_RAW_CAN_SUB_DEVICE_ID 0x1001
> +#define ASEM_RAW_CAN_SUB_DEVICE_ID_BIS 0x1002
> +#define ASEM_RAW_CAN_RST_REGISTER 0x54
> +#define ASEM_RAW_CAN_RST_MASK_CAN1 0x20
> +#define ASEM_RAW_CAN_RST_MASK_CAN2 0x04
> +
> static void plx_pci_reset_common(struct pci_dev *pdev);
> static void plx9056_pci_reset_common(struct pci_dev *pdev);
> static void plx_pci_reset_marathon_pci(struct pci_dev *pdev);
> static void plx_pci_reset_marathon_pcie(struct pci_dev *pdev);
> +static void plx_pci_reset_asem_dual_can_raw(struct pci_dev *pdev);
>
> struct plx_pci_channel_map {
> u32 bar;
> @@ -269,6 +285,14 @@ static struct plx_pci_card_info plx_pci_card_info_moxa = {
> /* based on PLX9052 */
> };
>
> +static struct plx_pci_card_info plx_pci_card_info_asem_dual_can = {
> + "ASEM Dual CAN raw PCI", 2,
> + PLX_PCI_CAN_CLOCK, ASEM_PCI_OCR, PLX_PCI_CDR,
> + {0, 0x00, 0x00}, { {2, 0x00, 0x00}, {4, 0x00, 0x00} },
> + &plx_pci_reset_asem_dual_can_raw
> + /* based on PLX9030 */
> +};
> +
> static const struct pci_device_id plx_pci_tbl[] = {
> {
> /* Adlink PCI-7841/cPCI-7841 */
> @@ -375,6 +399,20 @@ static const struct pci_device_id plx_pci_tbl[] = {
> 0, 0,
> (kernel_ulong_t)&plx_pci_card_info_moxa
> },
> + {
> + /* ASEM Dual CAN raw */
> + ASEM_RAW_CAN_VENDOR_ID, ASEM_RAW_CAN_DEVICE_ID,
> + ASEM_RAW_CAN_SUB_VENDOR_ID, ASEM_RAW_CAN_SUB_DEVICE_ID,
> + 0, 0,
> + (kernel_ulong_t)&plx_pci_card_info_asem_dual_can
> + },
> + {
> + /* ASEM Dual CAN raw -new model */
> + ASEM_RAW_CAN_VENDOR_ID, ASEM_RAW_CAN_DEVICE_ID,
> + ASEM_RAW_CAN_SUB_VENDOR_ID, ASEM_RAW_CAN_SUB_DEVICE_ID_BIS,
> + 0, 0,
> + (kernel_ulong_t)&plx_pci_card_info_asem_dual_can
> + },
> { 0,}
> };
> MODULE_DEVICE_TABLE(pci, plx_pci_tbl);
> @@ -524,6 +562,33 @@ static void plx_pci_reset_marathon_pcie(struct pci_dev *pdev)
> }
> }
>
> +/* Special reset function for ASEM Dual CAN raw card */
> +static void plx_pci_reset_asem_dual_can_raw(struct pci_dev *pdev)
> +{
> + void __iomem *bar0_addr;
> + static const int reset_bar;
> + u8 tmpval;
> +
> + plx_pci_reset_common(pdev);
> +
> + bar0_addr = pci_iomap(pdev, reset_bar, 0);
> + if (!bar0_addr) {
> + dev_err(&pdev->dev, "Failed to remap reset "
> + "space %d (BAR%d)\n", 0, reset_bar);
Please put the string into just one line.
> + return;
> + }
> +
> + /* reset the two SJA1000 chips */
> + tmpval = ioread8(bar0_addr + ASEM_RAW_CAN_RST_REGISTER);
> + tmpval &= ~(ASEM_RAW_CAN_RST_MASK_CAN1 | ASEM_RAW_CAN_RST_MASK_CAN2);
> + iowrite8(tmpval, bar0_addr + ASEM_RAW_CAN_RST_REGISTER);
> + usleep_range(300, 400);
> + tmpval |= ASEM_RAW_CAN_RST_MASK_CAN1 | ASEM_RAW_CAN_RST_MASK_CAN2;
> + iowrite8(tmpval, bar0_addr + ASEM_RAW_CAN_RST_REGISTER);
> + usleep_range(300, 400);
> + pci_iounmap(pdev, bar0_addr);
> +}
> +
> static void plx_pci_del_card(struct pci_dev *pdev)
> {
> struct plx_pci_card *card = pci_get_drvdata(pdev);
>
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* [PATCH v2] can: sja1000: plx_pci: add support for ASEM CAN raw device
From: Flavio Suligoi @ 2018-08-06 13:17 UTC (permalink / raw)
To: Wolfgang Grandegger, Marc Kleine-Budde
Cc: David S . Miller, linux-can, netdev, linux-kernel, Flavio Suligoi
In-Reply-To: <a6b6906d-6f53-9bf2-d87e-49ae3f208f00@pengutronix.de>
This patch adds support for ASEM opto-isolated dual channels
CAN raw device (http://www.asem.it)
Signed-off-by: Flavio Suligoi <f.suligoi@asem.it>
---
v2: - renamed ASEM_... constants to reduce space size;
- remove "else" in "plx_pci_reset_asem_dual_can_raw" function to avoid
strings breaking
drivers/net/can/sja1000/Kconfig | 1 +
drivers/net/can/sja1000/plx_pci.c | 67 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig
index 1e65cb6..f6dc899 100644
--- a/drivers/net/can/sja1000/Kconfig
+++ b/drivers/net/can/sja1000/Kconfig
@@ -88,6 +88,7 @@ config CAN_PLX_PCI
- TEWS TECHNOLOGIES TPMC810 card (http://www.tews.com/)
- IXXAT Automation PC-I 04/PCI card (http://www.ixxat.com/)
- Connect Tech Inc. CANpro/104-Plus Opto (CRG001) card (http://www.connecttech.com)
+ - ASEM CAN raw - 2 isolated CAN channels (www.asem.it)
config CAN_TSCAN1
tristate "TS-CAN1 PC104 boards"
diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c
index f8ff25c..d8dfa06 100644
--- a/drivers/net/can/sja1000/plx_pci.c
+++ b/drivers/net/can/sja1000/plx_pci.c
@@ -46,7 +46,8 @@ MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, "
"esd CAN-PCIe/2000, "
"Connect Tech Inc. CANpro/104-Plus Opto (CRG001), "
"IXXAT PC-I 04/PCI, "
- "ELCUS CAN-200-PCI")
+ "ELCUS CAN-200-PCI, "
+ "ASEM DUAL CAN-RAW")
MODULE_LICENSE("GPL v2");
#define PLX_PCI_MAX_CHAN 2
@@ -70,7 +71,9 @@ struct plx_pci_card {
*/
#define PLX_LINT1_EN 0x1 /* Local interrupt 1 enable */
+#define PLX_LINT1_POL (1 << 1) /* Local interrupt 1 polarity */
#define PLX_LINT2_EN (1 << 3) /* Local interrupt 2 enable */
+#define PLX_LINT2_POL (1 << 4) /* Local interrupt 1 polarity */
#define PLX_PCI_INT_EN (1 << 6) /* PCI Interrupt Enable */
#define PLX_PCI_RESET (1 << 30) /* PCI Adapter Software Reset */
@@ -92,6 +95,9 @@ struct plx_pci_card {
*/
#define PLX_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL)
+/* OCR setting for ASEM Dual CAN raw */
+#define ASEM_PCI_OCR 0xfe
+
/*
* In the CDR register, you should set CBP to 1.
* You will probably also want to set the clock divider value to 7
@@ -145,10 +151,20 @@ struct plx_pci_card {
#define MOXA_PCI_VENDOR_ID 0x1393
#define MOXA_PCI_DEVICE_ID 0x0100
+#define ASEM_RAW_CAN_VENDOR_ID 0x10b5
+#define ASEM_RAW_CAN_DEVICE_ID 0x9030
+#define ASEM_RAW_CAN_SUB_VENDOR_ID 0x3000
+#define ASEM_RAW_CAN_SUB_DEVICE_ID 0x1001
+#define ASEM_RAW_CAN_SUB_DEVICE_ID_BIS 0x1002
+#define ASEM_RAW_CAN_RST_REGISTER 0x54
+#define ASEM_RAW_CAN_RST_MASK_CAN1 0x20
+#define ASEM_RAW_CAN_RST_MASK_CAN2 0x04
+
static void plx_pci_reset_common(struct pci_dev *pdev);
static void plx9056_pci_reset_common(struct pci_dev *pdev);
static void plx_pci_reset_marathon_pci(struct pci_dev *pdev);
static void plx_pci_reset_marathon_pcie(struct pci_dev *pdev);
+static void plx_pci_reset_asem_dual_can_raw(struct pci_dev *pdev);
struct plx_pci_channel_map {
u32 bar;
@@ -269,6 +285,14 @@ static struct plx_pci_card_info plx_pci_card_info_moxa = {
/* based on PLX9052 */
};
+static struct plx_pci_card_info plx_pci_card_info_asem_dual_can = {
+ "ASEM Dual CAN raw PCI", 2,
+ PLX_PCI_CAN_CLOCK, ASEM_PCI_OCR, PLX_PCI_CDR,
+ {0, 0x00, 0x00}, { {2, 0x00, 0x00}, {4, 0x00, 0x00} },
+ &plx_pci_reset_asem_dual_can_raw
+ /* based on PLX9030 */
+};
+
static const struct pci_device_id plx_pci_tbl[] = {
{
/* Adlink PCI-7841/cPCI-7841 */
@@ -375,6 +399,20 @@ static const struct pci_device_id plx_pci_tbl[] = {
0, 0,
(kernel_ulong_t)&plx_pci_card_info_moxa
},
+ {
+ /* ASEM Dual CAN raw */
+ ASEM_RAW_CAN_VENDOR_ID, ASEM_RAW_CAN_DEVICE_ID,
+ ASEM_RAW_CAN_SUB_VENDOR_ID, ASEM_RAW_CAN_SUB_DEVICE_ID,
+ 0, 0,
+ (kernel_ulong_t)&plx_pci_card_info_asem_dual_can
+ },
+ {
+ /* ASEM Dual CAN raw -new model */
+ ASEM_RAW_CAN_VENDOR_ID, ASEM_RAW_CAN_DEVICE_ID,
+ ASEM_RAW_CAN_SUB_VENDOR_ID, ASEM_RAW_CAN_SUB_DEVICE_ID_BIS,
+ 0, 0,
+ (kernel_ulong_t)&plx_pci_card_info_asem_dual_can
+ },
{ 0,}
};
MODULE_DEVICE_TABLE(pci, plx_pci_tbl);
@@ -524,6 +562,33 @@ static void plx_pci_reset_marathon_pcie(struct pci_dev *pdev)
}
}
+/* Special reset function for ASEM Dual CAN raw card */
+static void plx_pci_reset_asem_dual_can_raw(struct pci_dev *pdev)
+{
+ void __iomem *bar0_addr;
+ static const int reset_bar;
+ u8 tmpval;
+
+ plx_pci_reset_common(pdev);
+
+ bar0_addr = pci_iomap(pdev, reset_bar, 0);
+ if (!bar0_addr) {
+ dev_err(&pdev->dev, "Failed to remap reset "
+ "space %d (BAR%d)\n", 0, reset_bar);
+ return;
+ }
+
+ /* reset the two SJA1000 chips */
+ tmpval = ioread8(bar0_addr + ASEM_RAW_CAN_RST_REGISTER);
+ tmpval &= ~(ASEM_RAW_CAN_RST_MASK_CAN1 | ASEM_RAW_CAN_RST_MASK_CAN2);
+ iowrite8(tmpval, bar0_addr + ASEM_RAW_CAN_RST_REGISTER);
+ usleep_range(300, 400);
+ tmpval |= ASEM_RAW_CAN_RST_MASK_CAN1 | ASEM_RAW_CAN_RST_MASK_CAN2;
+ iowrite8(tmpval, bar0_addr + ASEM_RAW_CAN_RST_REGISTER);
+ usleep_range(300, 400);
+ pci_iounmap(pdev, bar0_addr);
+}
+
static void plx_pci_del_card(struct pci_dev *pdev)
{
struct plx_pci_card *card = pci_get_drvdata(pdev);
--
2.7.4
^ permalink raw reply related
* Re: [pull request][net-next 00/10] Mellanox, mlx5 and devlink updates 2018-07-31
From: Eran Ben Elisha @ 2018-08-06 13:01 UTC (permalink / raw)
To: Jakub Kicinski
Cc: David Miller, saeedm, netdev, jiri, alexander.duyck, helgaas
In-Reply-To: <20180802155315.48aaab19@cakuba.netronome.com>
>>
>> Hi Dave,
>> I would like to re-state that this feature was not meant to be a generic
>> one. This feature was added in order to resolve a HW bug which exist in
>> a small portion of our devices.
>
> Would you mind describing the HW bug in more detail? To a outside
> reviewer it really looks like you're adding a feature. What are you
> working around? Is the lack of full AQM on the PCIe side of the chip
> considered a bug?
In multiple function environment, there is an issue with buffer
allocation per function which may lead to starvation. There is an HW WA
for mitigate this starvation by identifying this state and apply early
drop/mark.
>
>> Those params will be used only on those current HWs and won't be in
>> use for our future devices.
>
> I'm glad that is your plan today, however, customers may get used to
> the simple interface you're adding now. This means the API you are
> adding is effectively becoming an API other drivers may need to
> implement to keep compatibility with someone's proprietary
> orchestration.
This issue was refactored, thus no need to have this WA at all in future
NICs. So I don't believe we will end up in the situation you are describing.
It is less likely that other vendors will be facing the same issue and
will have to support such param. it was burn out of a bug and not as a
feature which other may follow.
>
>> During the discussions, several alternatives where offered to be used by
>> various members of the community. These alternatives includes TC and
>> enhancements to PCI configuration tools.
>>
>> Regarding the TC, from my perspective, this is not an option as:
>> 1) The HW mechanism handles multiple functions and therefore cannot be
>> configured on as a regular TC
>
> Could you elaborate? What are the multiple functions? You seem to be
> adding a knob to enable ECN marking and a knob for choosing between
> some predefined slopes.
PSB, The sloped are dynamic and enabled in a dynamic way.
Indeed, we are adding a very specific knob for very non standard
specific issue which can be used in addition to standard ECN marking.
>
> In what way would your solution not behave like a RED offload?
Existing Algo (RED, PIE, etc) are static, configurable. Our HW WA is
dynamic (dynamic slope), adjusted and auto enabled.
>
> With TC offload you'd also get a well-defined set of statistics, I
> presume right now you're planning on adding a set of ethtool -S
> counters?
>
>> 2) No PF + representors modeling can be applied here, this is a
>> MultiHost environment where one host is not aware to the other hosts,
>> and each is running on its own pci/driver. It is a device working mode
>> configuration.
>
> Yes, the multihost part makes it less pleasant. But this is a problem
> we have to tackle separately, at some point. It's not a center of
> attention here.
Agree, however the multihost part makes it non-transparent if we chose a
solution which is not based on direct vendor configuration. This will
lead to a bad user experience.
>
>> 3) The current HW W/A is very limited, maybe it has a similar algorithm
>> as WRED, but is being used for much simpler different use case (pci bus
>> congestion).
>
> No one is requesting full RED offload here.. if someone sets the
> parameters you can't support you simply won't offload them. And ignore
> the parameters which only make sense in software terms. Look at the
> docs for mlxsw:
>
> https://github.com/Mellanox/mlxsw/wiki/Queues-Management#offloading-red
>
> It says "not offloaded" in a number of places.
>
>> It cannot be compared to a standard TC capability (RED/WRED), and
>> defining it as a offload fully controlled by the user will be a big
>> misuse.
>
> It's generally preferable to implement a subset of exiting well defined
> API than create vendor knobs, hence hardly a misuse.
As written above, this is not the case here.
>
>> (for example, drop rate cannot be configured)
>
> I don't know what "configuring drop rate" means in case of RED..
>
>> regarding the PCI config tools, there was a consensus that such tool is
>> not acceptable as it is not a part of the PCI spec.
>
> As I said, this has nothing to do with PCI being the transport. The
> port you're running over could be serial, SPI or anything else. You
> have congestion on a port of a device, that's a networking problem.
>
>> Since module param/sysfs/debugfs/etc are no longer acceptable, and
>> current drivers still desired with a way to do some configurations to
>> the device/driver which cannot used standard Linux tool or by other
>> vendors, devlink params was developed (under the assumption that this
>> tool will be helpful for those needs, and those only).
>>
>> From my perspective, Devlink is the tool to configure the device for
>> handling such unexpected bugs, i.e "PCIe buffer congestion handling
>> workaround".
>
> Hm. Are you calling it a bug because you had to work around silicon
> limitation in firmware? Hm. I'm very intrigued by the framing :)
>
^ permalink raw reply
* Re: [endianness bug] cxgb4: mk_act_open_req() buggers ->{local,peer}_ip on big-endian hosts
From: Rahul Lakkireddy @ 2018-08-06 12:15 UTC (permalink / raw)
To: Al Viro; +Cc: ganeshgr, David Miller, netdev@vger.kernel.org
In-Reply-To: <20180805172238.GH15082@ZenIV.linux.org.uk>
On Sunday, August 08/05/18, 2018 at 22:52:38 +0530, Al Viro wrote:
> Unlike fs.val.lport and fs.val.fport, cxgb4_process_flow_match()
> sets fs.val.{l,f}ip to net-endian values without conversion - they come
> straight from flow_dissector_key_ipv4_addrs ->dst and ->src resp. So
> the assignment in mk_act_open_req() ought to be a straigh copy.
>
> As far as I know, T4 PCIe cards do exist, so it's not as if that
> thing could only be found on little-endian systems...
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
> diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
> index 00fc5f1afb1d..7dddb9e748b8 100644
> --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
> +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
> @@ -1038,10 +1038,8 @@ static void mk_act_open_req(struct filter_entry *f, struct sk_buff *skb,
> OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, qid_filterid));
> req->local_port = cpu_to_be16(f->fs.val.lport);
> req->peer_port = cpu_to_be16(f->fs.val.fport);
> - req->local_ip = f->fs.val.lip[0] | f->fs.val.lip[1] << 8 |
> - f->fs.val.lip[2] << 16 | f->fs.val.lip[3] << 24;
> - req->peer_ip = f->fs.val.fip[0] | f->fs.val.fip[1] << 8 |
> - f->fs.val.fip[2] << 16 | f->fs.val.fip[3] << 24;
> + memcpy(&req->local_ip, f->fs.val.lip, 4);
> + memcpy(&req->peer_ip, f->fs.val.fip, 4);
> req->opt0 = cpu_to_be64(NAGLE_V(f->fs.newvlan == VLAN_REMOVE ||
> f->fs.newvlan == VLAN_REWRITE) |
> DELACK_V(f->fs.hitcnts) |
Thanks for fix Al!
Acked-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
^ permalink raw reply
* Re: [endianness bug?] cxgb4_next_header .match_val/.match_mask should be net-endian
From: Rahul Lakkireddy @ 2018-08-06 12:12 UTC (permalink / raw)
To: Al Viro; +Cc: netdev@vger.kernel.org, ganeshgr, David S. Miller
In-Reply-To: <20180805152811.GF15082@ZenIV.linux.org.uk>
On Sunday, August 08/05/18, 2018 at 20:58:11 +0530, Al Viro wrote:
> AFAICS, cxgb4_next_header() expects to find match_val/match_mask in
> struct cxgb4_next_header stored as big-endian:
>
> /* Found a possible candidate. Find a key that
> * matches the corresponding offset, value, and
> * mask to jump to next header.
> */
> for (j = 0; j < cls->knode.sel->nkeys; j++) {
> off = cls->knode.sel->keys[j].off;
> val = cls->knode.sel->keys[j].val;
> mask = cls->knode.sel->keys[j].mask;
>
> if (next[i].match_off == off &&
> next[i].match_val == val &&
> next[i].match_mask == mask) {
> found = true;
> break;
> }
> }
>
> Here ->keys[] is struct tc_u32_key and there mask and val are definitely
> __be32. match_val and match_mask are never changed after initialization
> and they are set to:
>
> * .match_off = 8, .match_val = 0x600, .match_mask = 0xFF00
> meant to check for IPV4.Protocol == TCP, i.e. octet at offset 9 being 6
> * .match_off = 8, .match_val = 0x1100, .match_mask = 0xFF00
> meant to check for IPV4.Protocol == UDP, i.e. octet at offset 9 being 0x11
> * .match_off = 4, .match_val = 0x60000, .match_mask = 0xFF0000
> IPV6.NextHeader == TCP, i.e. octet at offset 6 being 6
> * .match_off = 4, .match_val = 0x110000, .match_mask = 0xFF0000
> IPV6.NextHeader == UDP, i.e. octet at offset 6 being 0x11
>
> On little-endian host those do yield the right values - e.g. 0x1100 is
> {0, 17, 0, 0}, etc. On big-endian, though, these will end up checking
> in IPv4 case the octet at offset 10 (i.e. upper 16 bits of checksum) and for IPv6
> - the octet at offset 5 (i.e. the lower 8 bits of payload length).
>
> Unless I'm misreading that code, it needs the following to do the right
> thing both on l-e and b-e. Comments?
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
> diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32_parse.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32_parse.h
> index a4b99edcc339..ec226b1cebf4 100644
> --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32_parse.h
> +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32_parse.h
> @@ -259,11 +259,11 @@ struct cxgb4_next_header {
> */
> static const struct cxgb4_next_header cxgb4_ipv4_jumps[] = {
> { .offset = 0, .offoff = 0, .shift = 6, .mask = 0xF,
> - .match_off = 8, .match_val = 0x600, .match_mask = 0xFF00,
> - .jump = cxgb4_tcp_fields },
> + .match_off = 8, .match_val = htonl(6 << 16),
> + .match_mask = htonl(0xff<<16), .jump = cxgb4_tcp_fields },
> { .offset = 0, .offoff = 0, .shift = 6, .mask = 0xF,
> - .match_off = 8, .match_val = 0x1100, .match_mask = 0xFF00,
> - .jump = cxgb4_udp_fields },
> + .match_off = 8, .match_val = htonl(17 << 16),
> + .match_mask = htonl(0xff<<16), .jump = cxgb4_udp_fields },
> { .jump = NULL }
> };
>
> @@ -272,11 +272,11 @@ static const struct cxgb4_next_header cxgb4_ipv4_jumps[] = {
> */
> static const struct cxgb4_next_header cxgb4_ipv6_jumps[] = {
> { .offset = 0x28, .offoff = 0, .shift = 0, .mask = 0,
> - .match_off = 4, .match_val = 0x60000, .match_mask = 0xFF0000,
> - .jump = cxgb4_tcp_fields },
> + .match_off = 4, .match_val = htonl(6 << 8),
> + .match_mask = htonl(0xff << 8), .jump = cxgb4_tcp_fields },
> { .offset = 0x28, .offoff = 0, .shift = 0, .mask = 0,
> - .match_off = 4, .match_val = 0x110000, .match_mask = 0xFF0000,
> - .jump = cxgb4_udp_fields },
> + .match_off = 4, .match_val = htonl(17 << 8),
> + .match_mask = htonl(0xff << 8), .jump = cxgb4_udp_fields },
> { .jump = NULL }
> };
>
Your observation is correct. The current logic is broken for
Big-Endian. Thanks for fixing it up Al!
As you've already found in the other email thread, ->mask also
needs to be fixed. Should be ".mask = htons(0xf << 8)".
Thanks,
Rahul
^ permalink raw reply
* [PATCH] can: sja1000: plx_pci: add support for ASEM CAN raw device
From: Flavio Suligoi @ 2018-08-06 12:00 UTC (permalink / raw)
To: Wolfgang Grandegger, Marc Kleine-Budde
Cc: David S . Miller, linux-can, netdev, linux-kernel, Flavio Suligoi
This patch adds support for ASEM opto-isolated dual channels
CAN raw device (http://www.asem.it)
Signed-off-by: Flavio Suligoi <f.suligoi@asem.it>
---
drivers/net/can/sja1000/Kconfig | 1 +
drivers/net/can/sja1000/plx_pci.c | 68 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 68 insertions(+), 1 deletion(-)
diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig
index 1e65cb6..f6dc899 100644
--- a/drivers/net/can/sja1000/Kconfig
+++ b/drivers/net/can/sja1000/Kconfig
@@ -88,6 +88,7 @@ config CAN_PLX_PCI
- TEWS TECHNOLOGIES TPMC810 card (http://www.tews.com/)
- IXXAT Automation PC-I 04/PCI card (http://www.ixxat.com/)
- Connect Tech Inc. CANpro/104-Plus Opto (CRG001) card (http://www.connecttech.com)
+ - ASEM CAN raw - 2 isolated CAN channels (www.asem.it)
config CAN_TSCAN1
tristate "TS-CAN1 PC104 boards"
diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c
index f8ff25c..864fe8d 100644
--- a/drivers/net/can/sja1000/plx_pci.c
+++ b/drivers/net/can/sja1000/plx_pci.c
@@ -46,7 +46,8 @@ MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, "
"esd CAN-PCIe/2000, "
"Connect Tech Inc. CANpro/104-Plus Opto (CRG001), "
"IXXAT PC-I 04/PCI, "
- "ELCUS CAN-200-PCI")
+ "ELCUS CAN-200-PCI, "
+ "ASEM DUAL CAN-RAW")
MODULE_LICENSE("GPL v2");
#define PLX_PCI_MAX_CHAN 2
@@ -70,7 +71,9 @@ struct plx_pci_card {
*/
#define PLX_LINT1_EN 0x1 /* Local interrupt 1 enable */
+#define PLX_LINT1_POL (1 << 1) /* Local interrupt 1 polarity */
#define PLX_LINT2_EN (1 << 3) /* Local interrupt 2 enable */
+#define PLX_LINT2_POL (1 << 4) /* Local interrupt 1 polarity */
#define PLX_PCI_INT_EN (1 << 6) /* PCI Interrupt Enable */
#define PLX_PCI_RESET (1 << 30) /* PCI Adapter Software Reset */
@@ -92,6 +95,9 @@ struct plx_pci_card {
*/
#define PLX_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL)
+/* OCR setting for ASEM Dual CAN raw */
+#define ASEM_PCI_OCR 0xfe
+
/*
* In the CDR register, you should set CBP to 1.
* You will probably also want to set the clock divider value to 7
@@ -145,10 +151,20 @@ struct plx_pci_card {
#define MOXA_PCI_VENDOR_ID 0x1393
#define MOXA_PCI_DEVICE_ID 0x0100
+#define ASEM_DUAL_CAN_VENDOR_ID 0x10b5
+#define ASEM_DUAL_CAN_DEVICE_ID 0x9030
+#define ASEM_DUAL_CAN_SUB_VENDOR_ID 0x3000
+#define ASEM_DUAL_CAN_SUB_DEVICE_ID 0x1001
+#define ASEM_DUAL_CAN_SUB_DEVICE_ID_BIS 0x1002
+#define ASEM_DUAL_CAN_RESET_REGISTER 0x54
+#define ASEM_DUAL_CAN_RESET_MASK_CAN1 0x20
+#define ASEM_DUAL_CAN_RESET_MASK_CAN2 0x04
+
static void plx_pci_reset_common(struct pci_dev *pdev);
static void plx9056_pci_reset_common(struct pci_dev *pdev);
static void plx_pci_reset_marathon_pci(struct pci_dev *pdev);
static void plx_pci_reset_marathon_pcie(struct pci_dev *pdev);
+static void plx_pci_reset_asem_dual_can_raw(struct pci_dev *pdev);
struct plx_pci_channel_map {
u32 bar;
@@ -269,6 +285,14 @@ static struct plx_pci_card_info plx_pci_card_info_moxa = {
/* based on PLX9052 */
};
+static struct plx_pci_card_info plx_pci_card_info_asem_dual_can = {
+ "ASEM Dual CAN raw PCI", 2,
+ PLX_PCI_CAN_CLOCK, ASEM_PCI_OCR, PLX_PCI_CDR,
+ {0, 0x00, 0x00}, { {2, 0x00, 0x00}, {4, 0x00, 0x00} },
+ &plx_pci_reset_asem_dual_can_raw
+ /* based on PLX9030 */
+};
+
static const struct pci_device_id plx_pci_tbl[] = {
{
/* Adlink PCI-7841/cPCI-7841 */
@@ -375,6 +399,20 @@ static const struct pci_device_id plx_pci_tbl[] = {
0, 0,
(kernel_ulong_t)&plx_pci_card_info_moxa
},
+ {
+ /* ASEM Dual CAN raw */
+ ASEM_DUAL_CAN_VENDOR_ID, ASEM_DUAL_CAN_DEVICE_ID,
+ ASEM_DUAL_CAN_SUB_VENDOR_ID, ASEM_DUAL_CAN_SUB_DEVICE_ID,
+ 0, 0,
+ (kernel_ulong_t)&plx_pci_card_info_asem_dual_can
+ },
+ {
+ /* ASEM Dual CAN raw -new model */
+ ASEM_DUAL_CAN_VENDOR_ID, ASEM_DUAL_CAN_DEVICE_ID,
+ ASEM_DUAL_CAN_SUB_VENDOR_ID, ASEM_DUAL_CAN_SUB_DEVICE_ID_BIS,
+ 0, 0,
+ (kernel_ulong_t)&plx_pci_card_info_asem_dual_can
+ },
{ 0,}
};
MODULE_DEVICE_TABLE(pci, plx_pci_tbl);
@@ -524,6 +562,34 @@ static void plx_pci_reset_marathon_pcie(struct pci_dev *pdev)
}
}
+/* Special reset function for ASEM Dual CAN raw card */
+static void plx_pci_reset_asem_dual_can_raw(struct pci_dev *pdev)
+{
+ void __iomem *bar0_addr;
+ static const int reset_bar;
+ u8 tmpval;
+
+ plx_pci_reset_common(pdev);
+
+ bar0_addr = pci_iomap(pdev, reset_bar, 0);
+ if (!bar0_addr) {
+ dev_err(&pdev->dev, "Failed to remap reset "
+ "space %d (BAR%d)\n", 0, reset_bar);
+ } else {
+ /* reset the two SJA1000 chips */
+ tmpval = ioread8(bar0_addr + ASEM_DUAL_CAN_RESET_REGISTER);
+ tmpval &= ~(ASEM_DUAL_CAN_RESET_MASK_CAN1 |
+ ASEM_DUAL_CAN_RESET_MASK_CAN2);
+ iowrite8(tmpval, bar0_addr + ASEM_DUAL_CAN_RESET_REGISTER);
+ usleep_range(300, 400);
+ tmpval |= ASEM_DUAL_CAN_RESET_MASK_CAN1 |
+ ASEM_DUAL_CAN_RESET_MASK_CAN2;
+ iowrite8(tmpval, bar0_addr + ASEM_DUAL_CAN_RESET_REGISTER);
+ usleep_range(300, 400);
+ pci_iounmap(pdev, bar0_addr);
+ }
+}
+
static void plx_pci_del_card(struct pci_dev *pdev)
{
struct plx_pci_card *card = pci_get_drvdata(pdev);
--
2.7.4
^ permalink raw reply related
* [PATCH net-next] ip6_tunnel: collect_md xmit: Use ip_tunnel_key's provided src address
From: Shmulik Ladkani @ 2018-08-06 12:00 UTC (permalink / raw)
To: David S . Miller; +Cc: Alexei Starovoitov, netdev, shmulik, Shmulik Ladkani
When using an ip6tnl device in collect_md mode, the xmit methods ignore
the ipv6.src field present in skb_tunnel_info's key, both for route
calculation purposes (flowi6 construction) and for assigning the
packet's final ipv6h->saddr.
This makes it impossible specifying a desired ipv6 local address in the
encapsulating header (for example, when using tc action tunnel_key).
This is also not aligned with behavior of ipip (ipv4) in collect_md
mode, where the key->u.ipv4.src gets used.
Fix, by assigning fl6.saddr with given key->u.ipv6.src.
In case ipv6.src is not specified, ip6_tnl_xmit uses existing saddr
selection code.
Signed-off-by: Shmulik Ladkani <shmulik.ladkani@gmail.com>
Reviewed-by: Eyal Birger <eyal.birger@gmail.com>
Fixes: 8d79266bc48c ("ip6_tunnel: add collect_md mode to IPv6 tunnels")
---
net/ipv6/ip6_tunnel.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 00e138a44cbb..820cebe0c687 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1113,7 +1113,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
dst = NULL;
goto tx_err_link_failure;
}
- if (t->parms.collect_md &&
+ if (t->parms.collect_md && ipv6_addr_any(&fl6->saddr) &&
ipv6_dev_get_saddr(net, ip6_dst_idev(dst)->dev,
&fl6->daddr, 0, &fl6->saddr))
goto tx_err_link_failure;
@@ -1255,6 +1255,7 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
key = &tun_info->key;
memset(&fl6, 0, sizeof(fl6));
fl6.flowi6_proto = IPPROTO_IPIP;
+ fl6.saddr = key->u.ipv6.src;
fl6.daddr = key->u.ipv6.dst;
fl6.flowlabel = key->label;
dsfield = key->tos;
@@ -1326,6 +1327,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
key = &tun_info->key;
memset(&fl6, 0, sizeof(fl6));
fl6.flowi6_proto = IPPROTO_IPV6;
+ fl6.saddr = key->u.ipv6.src;
fl6.daddr = key->u.ipv6.dst;
fl6.flowlabel = key->label;
dsfield = key->tos;
--
2.18.0
^ permalink raw reply related
* Re: [PATCH] Bluetooth: remove redundant variables 'adv_set' and 'cp'
From: Johan Hedberg @ 2018-08-06 14:09 UTC (permalink / raw)
To: YueHaibing; +Cc: marcel, linux-kernel, netdev, davem, linux-bluetooth
In-Reply-To: <20180806110851.8568-1-yuehaibing@huawei.com>
Hi YueHaibing,
On Mon, Aug 06, 2018, YueHaibing wrote:
> Variables 'adv_set' and 'cp' are being assigned but are never used hence
> they are redundant and can be removed.
>
> Cleans up clang warnings:
> net/bluetooth/hci_event.c:1135:29: warning: variable 'adv_set' set but not used [-Wunused-but-set-variable]
> net/bluetooth/mgmt.c:3359:39: warning: variable 'cp' set but not used [-Wunused-but-set-variable]
>
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
> ---
> net/bluetooth/hci_event.c | 3 ---
> net/bluetooth/mgmt.c | 3 ---
> 2 files changed, 6 deletions(-)
Applied to bluetooth-next. Thanks.
Johan
^ permalink raw reply
* e1000e driver stuck at 10Mbps after reconnection
From: Camille Bordignon @ 2018-08-06 11:59 UTC (permalink / raw)
To: Jeff Kirsher; +Cc: David S. Miller, intel-wired-lan, netdev
Hello,
Recently we experienced some issues with intel NIC (I219-LM and I219-V).
It seems that after a wire reconnection, auto-negotation "fails" and
link speed drips to 10 Mbps.
>From kernel logs:
[17616.346150] e1000e: enp0s31f6 NIC Link is Down
[17627.003322] e1000e: enp0s31f6 NIC Link is Up 10 Mbps Full Duplex, Flow Control: None
[17627.003325] e1000e 0000:00:1f.6 enp0s31f6: 10/100 speed: disabling TSO
$ethtool enp0s31f6
Settings for enp0s31f6:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supported pause frame use: No
Supports auto-negotiation: Yes
Supported FEC modes: Not reported
Advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Advertised pause frame use: No
Advertised auto-negotiation: Yes
Advertised FEC modes: Not reported
Speed: 10Mb/s
Duplex: Full
Port: Twisted Pair
PHYAD: 1
Transceiver: internal
Auto-negotiation: on
MDI-X: on (auto)
Supports Wake-on: pumbg
Wake-on: g
Current message level: 0x00000007 (7)
drv probe link
Link detected: yes
Notice that if disconnection last less than about 5 seconds,
nothing wrong happens.
And if after last failure, disconnection / connection occurs again and
last less than 5 seconds, link speed is back to 1000 Mbps.
[18075.350678] e1000e: enp0s31f6 NIC Link is Down
[18078.716245] e1000e: enp0s31f6 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None
The following patch seems to fix this issue.
However I don't clearly understand why.
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 3ba0c90e7055..763c013960f1 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -5069,7 +5069,7 @@ static bool e1000e_has_link(struct e1000_adapter *adapter)
case e1000_media_type_copper:
if (hw->mac.get_link_status) {
ret_val = hw->mac.ops.check_for_link(hw);
- link_active = !hw->mac.get_link_status;
+ link_active = false;
} else {
link_active = true;
}
Maybe this is related to watchdog task.
I've found out this fix by comparing with last commit that works fine :
commit 0b76aae741abb9d16d2c0e67f8b1e766576f897d.
However I don't know if this information is relevant.
Thank you.
Camille Bordignon
^ permalink raw reply related
* [PATCH RFC net-next 1/1] net/tls: Combined memory allocation for decryption request
From: Vakul Garg @ 2018-08-06 16:38 UTC (permalink / raw)
To: netdev; +Cc: borisp, aviadye, davejwatson, davem, Vakul Garg
In-Reply-To: <20180806163810.30880-1-vakul.garg@nxp.com>
For preparing decryption request, several memory chunks are required
(aead_req, sgin, sgout, iv, aad). For submitting the decrypt request to
an accelerator, it is required that the buffers which are read by the
accelerator must be dma-able and not come from stack. The buffers for
aad and iv can be separately kmalloced each, but it is inefficient.
This patch does a combined allocation for preparing decryption request
and then segments into aead_req || sgin || sgout || iv || aad.
Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
---
include/net/tls.h | 4 -
net/tls/tls_sw.c | 257 +++++++++++++++++++++++++++++++-----------------------
2 files changed, 148 insertions(+), 113 deletions(-)
diff --git a/include/net/tls.h b/include/net/tls.h
index d8b3b6578c01..d5c683e8bb22 100644
--- a/include/net/tls.h
+++ b/include/net/tls.h
@@ -124,10 +124,6 @@ struct tls_sw_context_rx {
struct sk_buff *recv_pkt;
u8 control;
bool decrypted;
-
- char rx_aad_ciphertext[TLS_AAD_SPACE_SIZE];
- char rx_aad_plaintext[TLS_AAD_SPACE_SIZE];
-
};
struct tls_record_info {
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index cd5ed2d1dbe8..a478b06fc015 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -118,19 +118,13 @@ static int tls_do_decryption(struct sock *sk,
struct scatterlist *sgout,
char *iv_recv,
size_t data_len,
- struct sk_buff *skb,
- gfp_t flags)
+ struct aead_request *aead_req)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
- struct aead_request *aead_req;
-
int ret;
- aead_req = aead_request_alloc(ctx->aead_recv, flags);
- if (!aead_req)
- return -ENOMEM;
-
+ aead_request_set_tfm(aead_req, ctx->aead_recv);
aead_request_set_ad(aead_req, TLS_AAD_SPACE_SIZE);
aead_request_set_crypt(aead_req, sgin, sgout,
data_len + tls_ctx->rx.tag_size,
@@ -139,8 +133,6 @@ static int tls_do_decryption(struct sock *sk,
crypto_req_done, &ctx->async_wait);
ret = crypto_wait_req(crypto_aead_decrypt(aead_req), &ctx->async_wait);
-
- aead_request_free(aead_req);
return ret;
}
@@ -727,8 +719,138 @@ static struct sk_buff *tls_wait_data(struct sock *sk, int flags,
return skb;
}
+/* This function decrypts the input skb into either out_iov or in out_sg
+ * or in skb buffers itself. The input parameter 'zc' indicates if
+ * zero-copy mode needs to be tried or not. With zero-copy mode, either
+ * out_iov or out_sg must be non-NULL. In case both out_iov and out_sg are
+ * NULL, then the decryption happens inside skb buffers itself, i.e.
+ * zero-copy gets disabled and 'zc' is updated.
+ */
+
+static int decrypt_internal(struct sock *sk, struct sk_buff *skb,
+ struct iov_iter *out_iov,
+ struct scatterlist *out_sg,
+ int *chunk, bool *zc)
+{
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
+ struct strp_msg *rxm = strp_msg(skb);
+ int n_sgin, n_sgout, nsg, mem_size, aead_size, err, pages = 0;
+ struct aead_request *aead_req;
+ struct sk_buff *unused;
+ u8 *aad, *iv, *mem = NULL;
+ struct scatterlist *sgin = NULL;
+ struct scatterlist *sgout = NULL;
+ const int data_len = rxm->full_len - tls_ctx->rx.overhead_size;
+
+ if (*zc && (out_iov || out_sg)) {
+ if (out_iov)
+ n_sgout = iov_iter_npages(out_iov, INT_MAX) + 1;
+ else if (out_sg)
+ n_sgout = sg_nents(out_sg);
+ else
+ goto no_zerocopy;
+
+ n_sgin = skb_nsg(skb, rxm->offset + tls_ctx->rx.prepend_size,
+ rxm->full_len - tls_ctx->rx.prepend_size);
+ } else {
+no_zerocopy:
+ n_sgout = 0;
+ *zc = false;
+ n_sgin = skb_cow_data(skb, 0, &unused);
+ }
+
+ if (n_sgin < 1)
+ return -EBADMSG;
+
+ /* Increment to accommodate AAD */
+ n_sgin = n_sgin + 1;
+
+ nsg = n_sgin + n_sgout;
+
+ aead_size = sizeof(*aead_req) + crypto_aead_reqsize(ctx->aead_recv);
+ mem_size = aead_size + (nsg * sizeof(struct scatterlist));
+ mem_size = mem_size + TLS_AAD_SPACE_SIZE;
+ mem_size = mem_size + crypto_aead_ivsize(ctx->aead_recv);
+
+ /* Allocate a single block of memory which contains
+ * aead_req || sgin[] || sgout[] || aad || iv.
+ * This order achieves correct alignment for aead_req, sgin, sgout.
+ */
+ mem = kmalloc(mem_size, sk->sk_allocation);
+ if (!mem)
+ return -ENOMEM;
+
+ /* Segment the allocated memory */
+ aead_req = (struct aead_request *)mem;
+ sgin = (struct scatterlist *)(mem + aead_size);
+ sgout = sgin + n_sgin;
+ aad = (u8 *)(sgout + n_sgout);
+ iv = aad + TLS_AAD_SPACE_SIZE;
+
+ /* Prepare IV */
+ err = skb_copy_bits(skb, rxm->offset + TLS_HEADER_SIZE,
+ iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
+ tls_ctx->rx.iv_size);
+ if (err < 0) {
+ kfree(mem);
+ return err;
+ }
+ memcpy(iv, tls_ctx->rx.iv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
+
+ /* Prepare AAD */
+ tls_make_aad(aad, rxm->full_len - tls_ctx->rx.overhead_size,
+ tls_ctx->rx.rec_seq, tls_ctx->rx.rec_seq_size,
+ ctx->control);
+
+ /* Prepare sgin */
+ sg_init_table(sgin, n_sgin);
+ sg_set_buf(&sgin[0], aad, TLS_AAD_SPACE_SIZE);
+ err = skb_to_sgvec(skb, &sgin[1],
+ rxm->offset + tls_ctx->rx.prepend_size,
+ rxm->full_len - tls_ctx->rx.prepend_size);
+ if (err < 0) {
+ kfree(mem);
+ return err;
+ }
+
+ if (n_sgout) {
+ if (out_iov) {
+ sg_init_table(sgout, n_sgout);
+ sg_set_buf(&sgout[0], aad, TLS_AAD_SPACE_SIZE);
+
+ *chunk = 0;
+ err = zerocopy_from_iter(sk, out_iov, data_len, &pages,
+ chunk, &sgout[1],
+ (n_sgout - 1), false);
+ if (err < 0)
+ goto fallback_to_reg_recv;
+ } else if (out_sg) {
+ memcpy(sgout, out_sg, n_sgout * sizeof(*sgout));
+ } else {
+ goto fallback_to_reg_recv;
+ }
+ } else {
+fallback_to_reg_recv:
+ sgout = sgin;
+ pages = 0;
+ *chunk = 0;
+ *zc = false;
+ }
+
+ /* Prepare and submit AEAD request */
+ err = tls_do_decryption(sk, sgin, sgout, iv, data_len, aead_req);
+
+ /* Release the pages in case iov was mapped to pages */
+ for (; pages > 0; pages--)
+ put_page(sg_page(&sgout[pages]));
+
+ kfree(mem);
+ return err;
+}
+
static int decrypt_skb_update(struct sock *sk, struct sk_buff *skb,
- struct scatterlist *sgout, bool *zc)
+ struct iov_iter *dest, int *chunk, bool *zc)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
@@ -741,7 +863,7 @@ static int decrypt_skb_update(struct sock *sk, struct sk_buff *skb,
return err;
#endif
if (!ctx->decrypted) {
- err = decrypt_skb(sk, skb, sgout);
+ err = decrypt_internal(sk, skb, dest, NULL, chunk, zc);
if (err < 0)
return err;
} else {
@@ -760,67 +882,10 @@ static int decrypt_skb_update(struct sock *sk, struct sk_buff *skb,
int decrypt_skb(struct sock *sk, struct sk_buff *skb,
struct scatterlist *sgout)
{
- struct tls_context *tls_ctx = tls_get_ctx(sk);
- struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
- char iv[TLS_CIPHER_AES_GCM_128_SALT_SIZE + MAX_IV_SIZE];
- struct scatterlist sgin_arr[MAX_SKB_FRAGS + 2];
- struct scatterlist *sgin = &sgin_arr[0];
- struct strp_msg *rxm = strp_msg(skb);
- int ret, nsg;
- struct sk_buff *unused;
-
- ret = skb_copy_bits(skb, rxm->offset + TLS_HEADER_SIZE,
- iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
- tls_ctx->rx.iv_size);
- if (ret < 0)
- return ret;
-
- memcpy(iv, tls_ctx->rx.iv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
- if (!sgout) {
- nsg = skb_cow_data(skb, 0, &unused);
- } else {
- nsg = skb_nsg(skb,
- rxm->offset + tls_ctx->rx.prepend_size,
- rxm->full_len - tls_ctx->rx.prepend_size);
- if (nsg <= 0)
- return nsg;
- }
-
- // We need one extra for ctx->rx_aad_ciphertext
- nsg++;
-
- if (nsg > ARRAY_SIZE(sgin_arr))
- sgin = kmalloc_array(nsg, sizeof(*sgin), sk->sk_allocation);
-
- if (!sgout)
- sgout = sgin;
-
- sg_init_table(sgin, nsg);
- sg_set_buf(&sgin[0], ctx->rx_aad_ciphertext, TLS_AAD_SPACE_SIZE);
-
- nsg = skb_to_sgvec(skb, &sgin[1],
- rxm->offset + tls_ctx->rx.prepend_size,
- rxm->full_len - tls_ctx->rx.prepend_size);
- if (nsg < 0) {
- ret = nsg;
- goto out;
- }
-
- tls_make_aad(ctx->rx_aad_ciphertext,
- rxm->full_len - tls_ctx->rx.overhead_size,
- tls_ctx->rx.rec_seq,
- tls_ctx->rx.rec_seq_size,
- ctx->control);
-
- ret = tls_do_decryption(sk, sgin, sgout, iv,
- rxm->full_len - tls_ctx->rx.overhead_size,
- skb, sk->sk_allocation);
-
-out:
- if (sgin != &sgin_arr[0])
- kfree(sgin);
+ bool zc = true;
+ int chunk;
- return ret;
+ return decrypt_internal(sk, skb, NULL, sgout, &chunk, &zc);
}
static bool tls_sw_advance_skb(struct sock *sk, struct sk_buff *skb,
@@ -899,43 +964,17 @@ int tls_sw_recvmsg(struct sock *sk,
}
if (!ctx->decrypted) {
- int page_count;
- int to_copy;
-
- page_count = iov_iter_npages(&msg->msg_iter,
- MAX_SKB_FRAGS);
- to_copy = rxm->full_len - tls_ctx->rx.overhead_size;
- if (!is_kvec && to_copy <= len && page_count < MAX_SKB_FRAGS &&
- likely(!(flags & MSG_PEEK))) {
- struct scatterlist sgin[MAX_SKB_FRAGS + 1];
- int pages = 0;
+ int to_copy = rxm->full_len - tls_ctx->rx.overhead_size;
+ if (!is_kvec && to_copy <= len &&
+ likely(!(flags & MSG_PEEK)))
zc = true;
- sg_init_table(sgin, MAX_SKB_FRAGS + 1);
- sg_set_buf(&sgin[0], ctx->rx_aad_plaintext,
- TLS_AAD_SPACE_SIZE);
-
- err = zerocopy_from_iter(sk, &msg->msg_iter,
- to_copy, &pages,
- &chunk, &sgin[1],
- MAX_SKB_FRAGS, false);
- if (err < 0)
- goto fallback_to_reg_recv;
-
- err = decrypt_skb_update(sk, skb, sgin, &zc);
- for (; pages > 0; pages--)
- put_page(sg_page(&sgin[pages]));
- if (err < 0) {
- tls_err_abort(sk, EBADMSG);
- goto recv_end;
- }
- } else {
-fallback_to_reg_recv:
- err = decrypt_skb_update(sk, skb, NULL, &zc);
- if (err < 0) {
- tls_err_abort(sk, EBADMSG);
- goto recv_end;
- }
+
+ err = decrypt_skb_update(sk, skb, &msg->msg_iter,
+ &chunk, &zc);
+ if (err < 0) {
+ tls_err_abort(sk, EBADMSG);
+ goto recv_end;
}
ctx->decrypted = true;
}
@@ -986,7 +1025,7 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos,
int err = 0;
long timeo;
int chunk;
- bool zc;
+ bool zc = false;
lock_sock(sk);
@@ -1003,7 +1042,7 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos,
}
if (!ctx->decrypted) {
- err = decrypt_skb_update(sk, skb, NULL, &zc);
+ err = decrypt_skb_update(sk, skb, NULL, &chunk, &zc);
if (err < 0) {
tls_err_abort(sk, EBADMSG);
--
2.13.6
^ 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