* Re: [PATCH v2 net-next 0/2] virtio_net: Expand affinity to arbitrary numbers of cpu and vq
From: Michael S. Tsirkin @ 2018-08-12 8:44 UTC (permalink / raw)
To: Caleb Raitto
Cc: herbert, davem, arei.gonglei, jasowang, netdev, linux-crypto,
Caleb Raitto
In-Reply-To: <20180810011828.199888-1-caleb.raitto@gmail.com>
On Thu, Aug 09, 2018 at 06:18:27PM -0700, Caleb Raitto wrote:
> From: Caleb Raitto <caraitto@google.com>
>
> Virtio-net tries to pin each virtual queue rx and tx interrupt to a cpu if
> there are as many queues as cpus.
>
> Expand this heuristic to configure a reasonable affinity setting also
> when the number of cpus != the number of virtual queues.
>
> Patch 1 allows vqs to take an affinity mask with more than 1 cpu.
> Patch 2 generalizes the algorithm in virtnet_set_affinity beyond
> the case where #cpus == #vqs.
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Let's see where does it take us.
> v2 changes:
> Renamed "virtio_net: Make vp_set_vq_affinity() take a mask." to
> "virtio: Make vp_set_vq_affinity() take a mask."
>
> Tested:
>
> # 16 vCPU, 16 queue pairs, Debian 9 recent net-next kernel, GCE
>
> # Disable GCE scripts setting affinities during startup.
> #
> # Add the following to
> # /etc/default/instance_configs.cfg.template and reboot:
> [InstanceSetup]
> set_multiqueue = false
>
> $ cd /proc/irq
> $ for i in `seq 24 60` ; do sudo grep ".*" $i/smp_affinity_list; done
> 0-15
> 0
> 0
> 1
> 1
> 2
> 2
> 3
> 3
> 4
> 4
> 5
> 5
> 6
> 6
> 7
> 7
> 8
> 8
> 9
> 9
> 10
> 10
> 11
> 11
> 12
> 12
> 13
> 13
> 14
> 14
> 15
> 15
> 0-15
> 0-15
> 0-15
> 0-15
>
> $ cd /sys/class/net/eth0/queues/
> $ for i in `seq 0 15` ; do sudo grep ".*" tx-$i/xps_cpus; done
> 0001
> 0002
> 0004
> 0008
> 0010
> 0020
> 0040
> 0080
> 0100
> 0200
> 0400
> 0800
> 1000
> 2000
> 4000
> 8000
>
> # 16 vCPU, 15 queue pairs
> $ sudo ethtool -L eth0 combined 15
>
> $ cd /proc/irq
> $ for i in `seq 24 60` ; do sudo grep ".*" $i/smp_affinity_list; done
> 0-15
> 0-1
> 0-1
> 2
> 2
> 3
> 3
> 4
> 4
> 5
> 5
> 6
> 6
> 7
> 7
> 8
> 8
> 9
> 9
> 10
> 10
> 11
> 11
> 12
> 12
> 13
> 13
> 14
> 14
> 15
> 15
> 15
> 15
> 0-15
> 0-15
> 0-15
> 0-15
>
> $ cd /sys/class/net/eth0/queues/
> $ for i in `seq 0 14` ; do sudo grep ".*" tx-$i/xps_cpus; done
> 0003
> 0004
> 0008
> 0010
> 0020
> 0040
> 0080
> 0100
> 0200
> 0400
> 0800
> 1000
> 2000
> 4000
> 8000
>
> # 16 vCPU, 8 queue pairs
> $ sudo ethtool -L eth0 combined 8
>
> $ cd /proc/irq
> $ for i in `seq 24 60` ; do sudo grep ".*" $i/smp_affinity_list; done
> 0-15
> 0-1
> 0-1
> 2-3
> 2-3
> 4-5
> 4-5
> 6-7
> 6-7
> 8-9
> 8-9
> 10-11
> 10-11
> 12-13
> 12-13
> 14-15
> 14-15
> 9
> 9
> 10
> 10
> 11
> 11
> 12
> 12
> 13
> 13
> 14
> 14
> 15
> 15
> 15
> 15
> 0-15
> 0-15
> 0-15
> 0-15
>
> $ cd /sys/class/net/eth0/queues/
> $ for i in `seq 0 7` ; do sudo grep ".*" tx-$i/xps_cpus; done
> 0003
> 000c
> 0030
> 00c0
> 0300
> 0c00
> 3000
> c000
>
> # 15 vCPU, 16 queue pairs
> $ sudo ethtool -L eth0 combined 16
> $ sudo sh -c "echo 0 > /sys/devices/system/cpu/cpu15/online"
>
> $ cd /proc/irq
> $ for i in `seq 24 60` ; do sudo grep ".*" $i/smp_affinity_list; done
> 0-15
> 0
> 0
> 1
> 1
> 2
> 2
> 3
> 3
> 4
> 4
> 5
> 5
> 6
> 6
> 7
> 7
> 8
> 8
> 9
> 9
> 10
> 10
> 11
> 11
> 12
> 12
> 13
> 13
> 14
> 14
> 0
> 0
> 0-15
> 0-15
> 0-15
> 0-15
>
> $ cd /sys/class/net/eth0/queues/
> $ for i in `seq 0 15` ; do sudo grep ".*" tx-$i/xps_cpus; done
> 0001
> 0002
> 0004
> 0008
> 0010
> 0020
> 0040
> 0080
> 0100
> 0200
> 0400
> 0800
> 1000
> 2000
> 4000
> 0001
>
> # 8 vCPU, 16 queue pairs
> $ for i in `seq 8 15`; \
> do sudo sh -c "echo 0 > /sys/devices/system/cpu/cpu$i/online"; done
>
> $ cd /proc/irq
> $ for i in `seq 24 60` ; do sudo grep ".*" $i/smp_affinity_list; done
> 0-15
> 0
> 0
> 1
> 1
> 2
> 2
> 3
> 3
> 4
> 4
> 5
> 5
> 6
> 6
> 7
> 7
> 0
> 0
> 1
> 1
> 2
> 2
> 3
> 3
> 4
> 4
> 5
> 5
> 6
> 6
> 7
> 7
> 0-15
> 0-15
> 0-15
> 0-15
>
> $ cd /sys/class/net/eth0/queues/
> $ for i in `seq 0 15` ; do sudo grep ".*" tx-$i/xps_cpus; done
> 0001
> 0002
> 0004
> 0008
> 0010
> 0020
> 0040
> 0080
> 0001
> 0002
> 0004
> 0008
> 0010
> 0020
> 0040
> 0080
>
> Caleb Raitto (2):
> virtio: Make vp_set_vq_affinity() take a mask.
> virtio_net: Stripe queue affinities across cores.
>
> drivers/crypto/virtio/virtio_crypto_core.c | 4 +-
> drivers/net/virtio_net.c | 46 ++++++++++++++--------
> drivers/virtio/virtio_pci_common.c | 7 ++--
> drivers/virtio/virtio_pci_common.h | 2 +-
> include/linux/virtio_config.h | 7 ++--
> 5 files changed, 39 insertions(+), 27 deletions(-)
>
> --
> 2.18.0.597.ga71716f1ad-goog
^ permalink raw reply
* Re: [PATCH net-next 5/5] net: aquantia: bump driver version
From: Igor Russkikh @ 2018-08-12 7:53 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: Andrew Lunn, David S . Miller, netdev, Simon Edelhaus
In-Reply-To: <20180809122048.3f2d0938@cakuba.netronome.com>
>> Hope the above are good enough arguments to keep up version bumps.
>
> A reasonably successful strategy is to version your out-of-tree driver
> with corresponding kernel release versions. Flip the equation.
>
> E.g. current net-next will become 4.19, so all the features you're
> pushing now would in your GH repo be:
>
> 4.19.0.${extra_numbers_if_you_want}-gh
>
> And you still have single versioning scheme, but the "bump to version
> XYZ" commits now go into your local tree not the kernel.
>
> As Andrew said backports make driver versions less than useful. Not
> only feature backports to enterprise kernel, but bug fixes which have to
> go to stable.
>
Technically yes, thats a good and manageable suggestion.
However the problem here is a human factor.
Regular users are often aware that NIC drivers are regularly
get updates, fixes etc. And they logically assume there is a
driver version in there. And what user normally does first
time he/she buys new NIC is checking driver version in system.
Obviously what user use is `ethtool -i` since thats a documented and
the only user visible tool.
What we'll get here is totally uncorrelated versioning info between inkernel
driver (some ancient version or no version at all) and vendor driver.
This will confuse user as he/she will start thinking (for example) that his
in kernel driver is "bad" and has to be updated.
Another human factor is tech support personnel, who also expect NIC drivers
to have version. We'll get tons of requests sort of "why and when you'll update
your upstream driver". It is up to date. "But why its version is not updated then?"
A lot of technical reports from fields does not include kernel version, but
(since users talk about NIC) just an "ethtool -i" output. This'll confuse us
as we have to do more queries on kernel version.
These are all legitimate expectations from non-tech people and what we trying
to do now is to keep up inkernel versioning with our local versioning.
Thus, user now sees:
version: 2.0.3.0-kern (for inkernel driver)
or
version: 2.0.6.0 (for external driver)
and can at least judge whether he needs updates or if thats OK.
As a one liner sumup:
kernel have user visible 'ethtool -i' API. Why should we drop it and deprecate it?
BR, Igor
^ permalink raw reply
* [PATCH net-next 9/9] net: hns3: Add vlan filter setting by ethtool command -K
From: Salil Mehta @ 2018-08-12 9:47 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil.lnk, netdev,
linux-kernel, linuxarm
In-Reply-To: <20180812094738.14852-1-salil.mehta@huawei.com>
From: Peng Li <lipeng321@huawei.com>
Revision(0x20) HW does not support enabling or disabling individual
netdev's HW_VLAN_CTAG_FILTER feature, and Revision(0x21) supports
enabling or disabling individual netdev's HW_VLAN_CTAG_FILTER
feature.
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index b28c7e142308..3554dca7a680 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -1673,6 +1673,9 @@ static struct pci_driver hns3_driver = {
/* set default feature to hns3 */
static void hns3_set_default_feature(struct net_device *netdev)
{
+ struct hnae3_handle *h = hns3_get_handle(netdev);
+ struct pci_dev *pdev = h->pdev;
+
netdev->priv_flags |= IFF_UNICAST_FLT;
netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
@@ -1706,6 +1709,9 @@ static void hns3_set_default_feature(struct net_device *netdev)
NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_GRE |
NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_GSO_UDP_TUNNEL_CSUM;
+
+ if (pdev->revision != 0x20)
+ netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
}
static int hns3_alloc_buffer(struct hns3_enet_ring *ring,
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 8/9] net: hns3: Set tx ring' tc info when netdev is up
From: Salil Mehta @ 2018-08-12 9:47 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil.lnk, netdev,
linux-kernel, linuxarm, Yunsheng Lin
In-Reply-To: <20180812094738.14852-1-salil.mehta@huawei.com>
From: Yunsheng Lin <linyunsheng@huawei.com>
The HNS3_RING_TX_RING_TC_REG register is used to map tx ring to
specific tc, the tx queue to tc mapping is needed by the hardware
to do the correct tx schedule.
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 24 ++++++++++++++++++++++++
drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 1 +
2 files changed, 25 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index b7b9ee3f4d20..b28c7e142308 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -2974,6 +2974,28 @@ static void hns3_init_ring_hw(struct hns3_enet_ring *ring)
}
}
+static void hns3_init_tx_ring_tc(struct hns3_nic_priv *priv)
+{
+ struct hnae3_knic_private_info *kinfo = &priv->ae_handle->kinfo;
+ int i;
+
+ for (i = 0; i < HNAE3_MAX_TC; i++) {
+ struct hnae3_tc_info *tc_info = &kinfo->tc_info[i];
+ int j;
+
+ if (!tc_info->enable)
+ continue;
+
+ for (j = 0; j < tc_info->tqp_count; j++) {
+ struct hnae3_queue *q;
+
+ q = priv->ring_data[tc_info->tqp_offset + j].ring->tqp;
+ hns3_write_dev(q, HNS3_RING_TX_RING_TC_REG,
+ tc_info->tc);
+ }
+ }
+}
+
int hns3_init_all_ring(struct hns3_nic_priv *priv)
{
struct hnae3_handle *h = priv->ae_handle;
@@ -3385,6 +3407,8 @@ int hns3_nic_reset_all_ring(struct hnae3_handle *h)
rx_ring->next_to_use = 0;
}
+ hns3_init_tx_ring_tc(priv);
+
return 0;
}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
index 0f071a0f4ff9..a02a96aee2a2 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
@@ -37,6 +37,7 @@ enum hns3_nic_state {
#define HNS3_RING_TX_RING_BASEADDR_L_REG 0x00040
#define HNS3_RING_TX_RING_BASEADDR_H_REG 0x00044
#define HNS3_RING_TX_RING_BD_NUM_REG 0x00048
+#define HNS3_RING_TX_RING_TC_REG 0x00050
#define HNS3_RING_TX_RING_TAIL_REG 0x00058
#define HNS3_RING_TX_RING_HEAD_REG 0x0005C
#define HNS3_RING_TX_RING_FBDNUM_REG 0x00060
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 7/9] net: hns3: Remove tx ring BD len register in hns3_enet
From: Salil Mehta @ 2018-08-12 9:47 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil.lnk, netdev,
linux-kernel, linuxarm, Yunsheng Lin
In-Reply-To: <20180812094738.14852-1-salil.mehta@huawei.com>
From: Yunsheng Lin <linyunsheng@huawei.com>
There is no HNS3_RING_TX_RING_BD_LEN_REG register according
to UM, so this patch removes it.
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 2 --
drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 1 -
2 files changed, 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index a64d69c87f13..b7b9ee3f4d20 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -2969,8 +2969,6 @@ static void hns3_init_ring_hw(struct hns3_enet_ring *ring)
hns3_write_dev(q, HNS3_RING_TX_RING_BASEADDR_H_REG,
(u32)((dma >> 31) >> 1));
- hns3_write_dev(q, HNS3_RING_TX_RING_BD_LEN_REG,
- hns3_buf_size2type(ring->buf_size));
hns3_write_dev(q, HNS3_RING_TX_RING_BD_NUM_REG,
ring->desc_num / 8 - 1);
}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
index e4b4a8f2ceaa..0f071a0f4ff9 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
@@ -37,7 +37,6 @@ enum hns3_nic_state {
#define HNS3_RING_TX_RING_BASEADDR_L_REG 0x00040
#define HNS3_RING_TX_RING_BASEADDR_H_REG 0x00044
#define HNS3_RING_TX_RING_BD_NUM_REG 0x00048
-#define HNS3_RING_TX_RING_BD_LEN_REG 0x0004C
#define HNS3_RING_TX_RING_TAIL_REG 0x00058
#define HNS3_RING_TX_RING_HEAD_REG 0x0005C
#define HNS3_RING_TX_RING_FBDNUM_REG 0x00060
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 6/9] net: hns3: Fix desc num set to default when setting channel
From: Salil Mehta @ 2018-08-12 9:47 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil.lnk, netdev,
linux-kernel, linuxarm, Yunsheng Lin
In-Reply-To: <20180812094738.14852-1-salil.mehta@huawei.com>
From: Yunsheng Lin <linyunsheng@huawei.com>
When user set the channel num using "ethtool -L ethX", the desc num
of BD will set to default value, which will cause desc num set by
user lost problem.
This patch fixes it by restoring the desc num set by user when setting
channel num.
Fixes: 09f2af6405b8 ("net: hns3: add support to modify tqps number")
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index c88f5e6a9b77..8510245705cc 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -1267,35 +1267,37 @@ static int hclge_map_tqps_to_func(struct hclge_dev *hdev, u16 func_id,
return ret;
}
-static int hclge_assign_tqp(struct hclge_vport *vport,
- struct hnae3_queue **tqp, u16 num_tqps)
+static int hclge_assign_tqp(struct hclge_vport *vport)
{
+ struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
struct hclge_dev *hdev = vport->back;
int i, alloced;
for (i = 0, alloced = 0; i < hdev->num_tqps &&
- alloced < num_tqps; i++) {
+ alloced < kinfo->num_tqps; i++) {
if (!hdev->htqp[i].alloced) {
hdev->htqp[i].q.handle = &vport->nic;
hdev->htqp[i].q.tqp_index = alloced;
- tqp[alloced] = &hdev->htqp[i].q;
+ hdev->htqp[i].q.desc_num = kinfo->num_desc;
+ kinfo->tqp[alloced] = &hdev->htqp[i].q;
hdev->htqp[i].alloced = true;
alloced++;
}
}
- vport->alloc_tqps = num_tqps;
+ vport->alloc_tqps = kinfo->num_tqps;
return 0;
}
-static int hclge_knic_setup(struct hclge_vport *vport, u16 num_tqps)
+static int hclge_knic_setup(struct hclge_vport *vport,
+ u16 num_tqps, u16 num_desc)
{
struct hnae3_handle *nic = &vport->nic;
struct hnae3_knic_private_info *kinfo = &nic->kinfo;
struct hclge_dev *hdev = vport->back;
int i, ret;
- kinfo->num_desc = hdev->num_desc;
+ kinfo->num_desc = num_desc;
kinfo->rx_buf_len = hdev->rx_buf_len;
kinfo->num_tc = min_t(u16, num_tqps, hdev->tm_info.num_tc);
kinfo->rss_size
@@ -1322,7 +1324,7 @@ static int hclge_knic_setup(struct hclge_vport *vport, u16 num_tqps)
if (!kinfo->tqp)
return -ENOMEM;
- ret = hclge_assign_tqp(vport, kinfo->tqp, kinfo->num_tqps);
+ ret = hclge_assign_tqp(vport);
if (ret)
dev_err(&hdev->pdev->dev, "fail to assign TQPs %d.\n", ret);
@@ -1388,7 +1390,7 @@ static int hclge_vport_setup(struct hclge_vport *vport, u16 num_tqps)
nic->numa_node_mask = hdev->numa_node_mask;
if (hdev->ae_dev->dev_type == HNAE3_DEV_KNIC) {
- ret = hclge_knic_setup(vport, num_tqps);
+ ret = hclge_knic_setup(vport, num_tqps, hdev->num_desc);
if (ret) {
dev_err(&hdev->pdev->dev, "knic setup failed %d\n",
ret);
@@ -5944,7 +5946,7 @@ static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num)
/* Free old tqps, and reallocate with new tqp number when nic setup */
hclge_release_tqp(vport);
- ret = hclge_knic_setup(vport, new_tqps_num);
+ ret = hclge_knic_setup(vport, new_tqps_num, kinfo->num_desc);
if (ret) {
dev_err(&hdev->pdev->dev, "setup nic fail, ret =%d\n", ret);
return ret;
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 5/9] net: hns3: Fix for vf vlan delete failed problem
From: Salil Mehta @ 2018-08-12 9:47 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil.lnk, netdev,
linux-kernel, linuxarm, Yunsheng Lin
In-Reply-To: <20180812094738.14852-1-salil.mehta@huawei.com>
From: Yunsheng Lin <linyunsheng@huawei.com>
There are only 128 entries in vf vlan table, if user has added
more than 128 vlan, fw will ignore it and disable the vf vlan
table. So when user deletes the vlan entry that has not been
set to vf vlan table, fw will return not found result and driver
treat that as error, which will cause vlan delete failed problem.
This patch fixes it by returning ok when fw returns not found
result.
Fixes: 9dba194574e3 ("{topost} net: hns3: fix for vlan table problem")
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 3b7cd6744280..c88f5e6a9b77 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -4684,9 +4684,17 @@ static int hclge_set_vf_vlan_common(struct hclge_dev *hdev, int vfid,
"Add vf vlan filter fail, ret =%d.\n",
req0->resp_code);
} else {
+#define HCLGE_VF_VLAN_DEL_NO_FOUND 1
if (!req0->resp_code)
return 0;
+ if (req0->resp_code == HCLGE_VF_VLAN_DEL_NO_FOUND) {
+ dev_warn(&hdev->pdev->dev,
+ "vlan %d filter is not in vf vlan table\n",
+ vlan);
+ return 0;
+ }
+
dev_err(&hdev->pdev->dev,
"Kill vf vlan filter fail, ret =%d.\n",
req0->resp_code);
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 4/9] net: hns3: Fix for phy link issue when using marvell phy driver
From: Salil Mehta @ 2018-08-12 9:47 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil.lnk, netdev,
linux-kernel, linuxarm, Jian Shen
In-Reply-To: <20180812094738.14852-1-salil.mehta@huawei.com>
From: Jian Shen <shenjian15@huawei.com>
For marvell phy m88e1510, bit SUPPORTED_FIBRE of phydev->supported
is default on. Both phy_resume() and phy_suspend() will check the
SUPPORTED_FIBRE bit and write register of fibre page.
Currently in hns3 driver, the SUPPORTED_FIBRE bit will be cleared
after phy_connect_direct() finished. Because phy_resume() is called
in phy_connect_direct(), and phy_suspend() is called when disconnect
phy device, so the operation for fibre page register is not symmetrical.
It will cause phy link issue when reload hns3 driver.
This patch fixes it by disable the SUPPORTED_FIBRE before connecting
phy.
This is a temporary scheme for DTS2018050311542. I'm contacking with
the FAE of marvell phy, wish to get a better way to deal with it.
Signed-off-by: Jian Shen <shenjian15@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
index 85a123d40e8b..398971a062f4 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
@@ -202,6 +202,8 @@ int hclge_mac_connect_phy(struct hclge_dev *hdev)
if (!phydev)
return 0;
+ phydev->supported &= ~SUPPORTED_FIBRE;
+
ret = phy_connect_direct(netdev, phydev,
hclge_mac_adjust_link,
PHY_INTERFACE_MODE_SGMII);
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 3/9] net: hns3: Fix for information of phydev lost problem when down/up
From: Salil Mehta @ 2018-08-12 9:47 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil.lnk, netdev,
linux-kernel, linuxarm, Fuyun Liang
In-Reply-To: <20180812094738.14852-1-salil.mehta@huawei.com>
From: Fuyun Liang <liangfuyun1@huawei.com>
Function call of phy_connect_direct will reinitialize phydev. Some
information like advertising will be lost. Phy_connect_direct only
needs to be called once. And driver can run well. This patch adds
some functions to ensure that phy_connect_direct is called only once
to solve the information of phydev lost problem occurring when we stop
the net and open it again.
Signed-off-by: Fuyun Liang <liangfuyun1@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 24 +++++++++++++++++----
.../ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c | 25 ++++++++++++++++++----
.../ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h | 4 +++-
3 files changed, 44 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 18ae11d8de73..3b7cd6744280 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -3782,7 +3782,7 @@ static int hclge_ae_start(struct hnae3_handle *handle)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
- int i, ret;
+ int i;
for (i = 0; i < vport->alloc_tqps; i++)
hclge_tqp_enable(hdev, i, 0, true);
@@ -3796,9 +3796,7 @@ static int hclge_ae_start(struct hnae3_handle *handle)
/* reset tqp stats */
hclge_reset_tqp_stats(handle);
- ret = hclge_mac_start_phy(hdev);
- if (ret)
- return ret;
+ hclge_mac_start_phy(hdev);
return 0;
}
@@ -5417,6 +5415,16 @@ static void hclge_get_mdix_mode(struct hnae3_handle *handle,
*tp_mdix = ETH_TP_MDI;
}
+static int hclge_init_instance_hw(struct hclge_dev *hdev)
+{
+ return hclge_mac_connect_phy(hdev);
+}
+
+static void hclge_uninit_instance_hw(struct hclge_dev *hdev)
+{
+ hclge_mac_disconnect_phy(hdev);
+}
+
static int hclge_init_client_instance(struct hnae3_client *client,
struct hnae3_ae_dev *ae_dev)
{
@@ -5436,6 +5444,13 @@ static int hclge_init_client_instance(struct hnae3_client *client,
if (ret)
return ret;
+ ret = hclge_init_instance_hw(hdev);
+ if (ret) {
+ client->ops->uninit_instance(&vport->nic,
+ 0);
+ return ret;
+ }
+
if (hdev->roce_client &&
hnae3_dev_roce_supported(hdev)) {
struct hnae3_client *rc = hdev->roce_client;
@@ -5498,6 +5513,7 @@ static void hclge_uninit_client_instance(struct hnae3_client *client,
if (client->type == HNAE3_CLIENT_ROCE)
return;
if (client->ops->uninit_instance) {
+ hclge_uninit_instance_hw(hdev);
client->ops->uninit_instance(&vport->nic, 0);
hdev->nic_client = NULL;
vport->nic.client = NULL;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
index 2065ee2fd358..85a123d40e8b 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
@@ -193,7 +193,7 @@ static void hclge_mac_adjust_link(struct net_device *netdev)
netdev_err(netdev, "failed to configure flow control.\n");
}
-int hclge_mac_start_phy(struct hclge_dev *hdev)
+int hclge_mac_connect_phy(struct hclge_dev *hdev)
{
struct net_device *netdev = hdev->vport[0].nic.netdev;
struct phy_device *phydev = hdev->hw.mac.phydev;
@@ -213,11 +213,29 @@ int hclge_mac_start_phy(struct hclge_dev *hdev)
phydev->supported &= HCLGE_PHY_SUPPORTED_FEATURES;
phydev->advertising = phydev->supported;
- phy_start(phydev);
-
return 0;
}
+void hclge_mac_disconnect_phy(struct hclge_dev *hdev)
+{
+ struct phy_device *phydev = hdev->hw.mac.phydev;
+
+ if (!phydev)
+ return;
+
+ phy_disconnect(phydev);
+}
+
+void hclge_mac_start_phy(struct hclge_dev *hdev)
+{
+ struct phy_device *phydev = hdev->hw.mac.phydev;
+
+ if (!phydev)
+ return;
+
+ phy_start(phydev);
+}
+
void hclge_mac_stop_phy(struct hclge_dev *hdev)
{
struct net_device *netdev = hdev->vport[0].nic.netdev;
@@ -227,5 +245,4 @@ void hclge_mac_stop_phy(struct hclge_dev *hdev)
return;
phy_stop(phydev);
- phy_disconnect(phydev);
}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h
index bb3ce35e0d66..5fbf7dddb5d9 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h
@@ -5,7 +5,9 @@
#define __HCLGE_MDIO_H
int hclge_mac_mdio_config(struct hclge_dev *hdev);
-int hclge_mac_start_phy(struct hclge_dev *hdev);
+int hclge_mac_connect_phy(struct hclge_dev *hdev);
+void hclge_mac_disconnect_phy(struct hclge_dev *hdev);
+void hclge_mac_start_phy(struct hclge_dev *hdev);
void hclge_mac_stop_phy(struct hclge_dev *hdev);
#endif
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 2/9] net: hns3: Fix for command format parsing error in hclge_is_all_function_id_zero
From: Salil Mehta @ 2018-08-12 9:47 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil.lnk, netdev,
linux-kernel, linuxarm, Xi Wang
In-Reply-To: <20180812094738.14852-1-salil.mehta@huawei.com>
From: Xi Wang <wangxi11@huawei.com>
According to the functional specification of hardward, the first
descriptor of response from command 'lookup vlan talbe' is not valid.
Currently, the first descriptor is parsed as normal value, which will
cause an expected error.
This patch fixes this problem by skipping the first descriptor.
Signed-off-by: Xi Wang <wangxi11@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 99dda5051f5f..18ae11d8de73 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -3930,7 +3930,7 @@ static bool hclge_is_all_function_id_zero(struct hclge_desc *desc)
#define HCLGE_FUNC_NUMBER_PER_DESC 6
int i, j;
- for (i = 0; i < HCLGE_DESC_NUMBER; i++)
+ for (i = 1; i < HCLGE_DESC_NUMBER; i++)
for (j = 0; j < HCLGE_FUNC_NUMBER_PER_DESC; j++)
if (desc[i].data[j])
return false;
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 1/9] net: hns3: Add support for serdes loopback selftest
From: Salil Mehta @ 2018-08-12 9:47 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil.lnk, netdev,
linux-kernel, linuxarm, Yunsheng Lin
In-Reply-To: <20180812094738.14852-1-salil.mehta@huawei.com>
From: Peng Li <lipeng321@huawei.com>
This patch adds support for serdes loopback selftest in hns3
driver.
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 7 ++-
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 12 +++++
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 57 +++++++++++++++++++++-
3 files changed, 73 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
index 80ba95d76260..f4710e498c59 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
@@ -53,7 +53,7 @@ static const struct hns3_stats hns3_rxq_stats[] = {
#define HNS3_TQP_STATS_COUNT (HNS3_TXQ_STATS_COUNT + HNS3_RXQ_STATS_COUNT)
-#define HNS3_SELF_TEST_TPYE_NUM 1
+#define HNS3_SELF_TEST_TPYE_NUM 2
#define HNS3_NIC_LB_TEST_PKT_NUM 1
#define HNS3_NIC_LB_TEST_RING_ID 0
#define HNS3_NIC_LB_TEST_PACKET_SIZE 128
@@ -78,6 +78,7 @@ static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en)
return -EOPNOTSUPP;
switch (loop) {
+ case HNAE3_MAC_INTER_LOOP_SERDES:
case HNAE3_MAC_INTER_LOOP_MAC:
ret = h->ae_algo->ops->set_loopback(h, loop, en);
break;
@@ -303,6 +304,10 @@ static void hns3_self_test(struct net_device *ndev,
st_param[HNAE3_MAC_INTER_LOOP_MAC][1] =
h->flags & HNAE3_SUPPORT_MAC_LOOPBACK;
+ st_param[HNAE3_MAC_INTER_LOOP_SERDES][0] = HNAE3_MAC_INTER_LOOP_SERDES;
+ st_param[HNAE3_MAC_INTER_LOOP_SERDES][1] =
+ h->flags & HNAE3_SUPPORT_SERDES_LOOPBACK;
+
if (if_running)
dev_close(ndev);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index cd0a4f228470..821d4c2f84bd 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -94,6 +94,7 @@ enum hclge_opcode_type {
HCLGE_OPC_QUERY_LINK_STATUS = 0x0307,
HCLGE_OPC_CONFIG_MAX_FRM_SIZE = 0x0308,
HCLGE_OPC_CONFIG_SPEED_DUP = 0x0309,
+ HCLGE_OPC_SERDES_LOOPBACK = 0x0315,
/* PFC/Pause commands */
HCLGE_OPC_CFG_MAC_PAUSE_EN = 0x0701,
@@ -775,6 +776,17 @@ struct hclge_reset_cmd {
u8 fun_reset_vfid;
u8 rsv[22];
};
+
+#define HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B BIT(0)
+#define HCLGE_CMD_SERDES_DONE_B BIT(0)
+#define HCLGE_CMD_SERDES_SUCCESS_B BIT(1)
+struct hclge_serdes_lb_cmd {
+ u8 mask;
+ u8 enable;
+ u8 result;
+ u8 rsv[21];
+};
+
#define HCLGE_DEFAULT_TX_BUF 0x4000 /* 16k bytes */
#define HCLGE_TOTAL_PKT_BUF 0x108000 /* 1.03125M bytes */
#define HCLGE_DEFAULT_DV 0xA000 /* 40k byte */
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index fc813b7f20e8..99dda5051f5f 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -787,9 +787,10 @@ static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset)
hdev->hw.mac.speed == HCLGE_MAC_SPEED_1G) {
count += 1;
handle->flags |= HNAE3_SUPPORT_MAC_LOOPBACK;
- } else {
- count = -EOPNOTSUPP;
}
+
+ count ++;
+ handle->flags |= HNAE3_SUPPORT_SERDES_LOOPBACK;
} else if (stringset == ETH_SS_STATS) {
count = ARRAY_SIZE(g_mac_stats_string) +
ARRAY_SIZE(g_all_32bit_stats_string) +
@@ -3670,6 +3671,55 @@ static int hclge_set_mac_loopback(struct hclge_dev *hdev, bool en)
return ret;
}
+static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en)
+{
+#define HCLGE_SERDES_RETRY_MS 10
+#define HCLGE_SERDES_RETRY_NUM 100
+ struct hclge_serdes_lb_cmd *req;
+ struct hclge_desc desc;
+ int ret, i = 0;
+
+ req = (struct hclge_serdes_lb_cmd *)&desc.data[0];
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SERDES_LOOPBACK, false);
+
+ if (en) {
+ req->enable = HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B;
+ req->mask = HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B;
+ } else {
+ req->mask = HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B;
+ }
+
+ ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "serdes loopback set fail, ret = %d\n", ret);
+ return ret;
+ }
+
+ do {
+ msleep(HCLGE_SERDES_RETRY_MS);
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SERDES_LOOPBACK,
+ true);
+ ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "serdes loopback get, ret = %d\n", ret);
+ return ret;
+ }
+ } while (++i < HCLGE_SERDES_RETRY_NUM &&
+ !(req->result & HCLGE_CMD_SERDES_DONE_B));
+
+ if (!(req->result & HCLGE_CMD_SERDES_DONE_B)) {
+ dev_err(&hdev->pdev->dev, "serdes loopback set timeout\n");
+ return -EBUSY;
+ } else if (!(req->result & HCLGE_CMD_SERDES_SUCCESS_B)) {
+ dev_err(&hdev->pdev->dev, "serdes loopback set failed in fw\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
static int hclge_set_loopback(struct hnae3_handle *handle,
enum hnae3_loop loop_mode, bool en)
{
@@ -3681,6 +3731,9 @@ static int hclge_set_loopback(struct hnae3_handle *handle,
case HNAE3_MAC_INTER_LOOP_MAC:
ret = hclge_set_mac_loopback(hdev, en);
break;
+ case HNAE3_MAC_INTER_LOOP_SERDES:
+ ret = hclge_set_serdes_loopback(hdev, en);
+ break;
default:
ret = -ENOTSUPP;
dev_err(&hdev->pdev->dev,
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 0/9] Misc bug fixes & small enhancements for HNS3 Driver
From: Salil Mehta @ 2018-08-12 9:47 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil.lnk, netdev,
linux-kernel, linuxarm
This patch-set presents some bug fixes and minor enhancements to
HNS3 Ethernet driver.
Fuyun Liang (1):
net: hns3: Fix for information of phydev lost problem when down/up
Jian Shen (1):
net: hns3: Fix for phy link issue when using marvell phy driver
Peng Li (2):
net: hns3: Add support for serdes loopback selftest
net: hns3: Add vlan filter setting by ethtool command -K
Xi Wang (1):
net: hns3: Fix for command format parsing error in
hclge_is_all_function_id_zero
Yunsheng Lin (4):
net: hns3: Fix for vf vlan delete failed problem
net: hns3: Fix desc num set to default when setting channel
net: hns3: Remove tx ring BD len register in hns3_enet
net: hns3: Set tx ring' tc info when netdev is up
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 32 +++++-
drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 2 +-
drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 7 +-
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 12 +++
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 113 +++++++++++++++++----
.../ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c | 27 ++++-
.../ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h | 4 +-
7 files changed, 171 insertions(+), 26 deletions(-)
--
2.11.0
^ permalink raw reply
* Re: [PATCH bpf-next 4/4] selftests/bpf: Selftest for bpf_skb_ancestor_cgroup_id
From: Yonghong Song @ 2018-08-12 6:58 UTC (permalink / raw)
To: Andrey Ignatov, netdev; +Cc: ast, daniel, tj, guro, kernel-team
In-Reply-To: <fd9428a9f03598da21caa2bb0e49c958f9c8daf3.1533965421.git.rdna@fb.com>
On 8/10/18 10:35 PM, Andrey Ignatov wrote:
> Add selftests for bpf_skb_ancestor_cgroup_id helper.
>
> test_skb_cgroup_id.sh prepares testing interface and adds tc qdisc and
> filter for it using BPF object compiled from test_skb_cgroup_id_kern.c
> program.
>
> BPF program in test_skb_cgroup_id_kern.c gets ancestor cgroup id using
> the new helper at different levels of cgroup hierarchy that skb belongs
> to, including root level and non-existing level, and saves it to the map
> where the key is the level of corresponding cgroup and the value is its
> id.
>
> To trigger BPF program, user space program test_skb_cgroup_id_user is
> run. It adds itself into testing cgroup and sends UDP datagram to
> link-local multicast address of testing interface. Then it reads cgroup
> ids saved in kernel for different levels from the BPF map and compares
> them with those in user space. They must be equal for every level of
> ancestry.
>
> Example of run:
> # ./test_skb_cgroup_id.sh
> Wait for testing link-local IP to become available ... OK
> Note: 8 bytes struct bpf_elf_map fixup performed due to size mismatch!
> [PASS]
I am not able to run the test on my FC27 based VM with the latest
bpf-next and the patch set.
[yhs@localhost bpf]$ sudo ./test_skb_cgroup_id.sh
Wait for testing link-local IP to become available .....ERROR: Timeout
waiting for test IP to become available.
[yhs@localhost bpf]$
I am able to run test_sock_addr.sh successfully.
$ sudo ./test_sock_addr.sh
Wait for testing IPv4/IPv6 to become available .
.. OK
Test case: bind4: load prog with wrong expected attach type .. [PASS]
Test case: bind4: attach prog with wrong attach type .. [PASS]
...
Test case: sendmsg6: deny call .. [PASS]
Summary: 27 PASSED, 0 FAILED
Maybe some issues in this addr ff02::1%${TEST_IF}?
>
> Signed-off-by: Andrey Ignatov <rdna@fb.com>
> ---
> tools/testing/selftests/bpf/Makefile | 9 +-
> .../selftests/bpf/test_skb_cgroup_id.sh | 61 ++++++
> .../selftests/bpf/test_skb_cgroup_id_kern.c | 47 +++++
> .../selftests/bpf/test_skb_cgroup_id_user.c | 187 ++++++++++++++++++
> 4 files changed, 301 insertions(+), 3 deletions(-)
> create mode 100755 tools/testing/selftests/bpf/test_skb_cgroup_id.sh
> create mode 100644 tools/testing/selftests/bpf/test_skb_cgroup_id_kern.c
> create mode 100644 tools/testing/selftests/bpf/test_skb_cgroup_id_user.c
>
> diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
> index daed162043c2..fff7fb1285fc 100644
> --- a/tools/testing/selftests/bpf/Makefile
> +++ b/tools/testing/selftests/bpf/Makefile
> @@ -34,7 +34,8 @@ TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test
> test_btf_haskv.o test_btf_nokv.o test_sockmap_kern.o test_tunnel_kern.o \
> test_get_stack_rawtp.o test_sockmap_kern.o test_sockhash_kern.o \
> test_lwt_seg6local.o sendmsg4_prog.o sendmsg6_prog.o test_lirc_mode2_kern.o \
> - get_cgroup_id_kern.o socket_cookie_prog.o test_select_reuseport_kern.o
> + get_cgroup_id_kern.o socket_cookie_prog.o test_select_reuseport_kern.o \
> + test_skb_cgroup_id_kern.o
>
> # Order correspond to 'make run_tests' order
> TEST_PROGS := test_kmod.sh \
> @@ -45,10 +46,11 @@ TEST_PROGS := test_kmod.sh \
> test_sock_addr.sh \
> test_tunnel.sh \
> test_lwt_seg6local.sh \
> - test_lirc_mode2.sh
> + test_lirc_mode2.sh \
> + test_skb_cgroup_id.sh
>
> # Compile but not part of 'make run_tests'
> -TEST_GEN_PROGS_EXTENDED = test_libbpf_open test_sock_addr
> +TEST_GEN_PROGS_EXTENDED = test_libbpf_open test_sock_addr test_skb_cgroup_id_user
>
> include ../lib.mk
>
> @@ -59,6 +61,7 @@ $(TEST_GEN_PROGS): $(BPFOBJ)
> $(TEST_GEN_PROGS_EXTENDED): $(OUTPUT)/libbpf.a
>
> $(OUTPUT)/test_dev_cgroup: cgroup_helpers.c
> +$(OUTPUT)/test_skb_cgroup_id_user: cgroup_helpers.c
> $(OUTPUT)/test_sock: cgroup_helpers.c
> $(OUTPUT)/test_sock_addr: cgroup_helpers.c
> $(OUTPUT)/test_socket_cookie: cgroup_helpers.c
> diff --git a/tools/testing/selftests/bpf/test_skb_cgroup_id.sh b/tools/testing/selftests/bpf/test_skb_cgroup_id.sh
> new file mode 100755
> index 000000000000..b75e9b52f06f
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/test_skb_cgroup_id.sh
> @@ -0,0 +1,61 @@
> +#!/bin/sh
> +# SPDX-License-Identifier: GPL-2.0
> +# Copyright (c) 2018 Facebook
> +
> +set -eu
> +
> +wait_for_ip()
> +{
> + local _i
> + echo -n "Wait for testing link-local IP to become available "
> + for _i in $(seq ${MAX_PING_TRIES}); do
> + echo -n "."
> + if ping -6 -q -c 1 -W 1 ff02::1%${TEST_IF} >/dev/null 2>&1; then
> + echo " OK"
> + return
> + fi
> + done
> + echo 1>&2 "ERROR: Timeout waiting for test IP to become available."
> + exit 1
> +}
> +
> +setup()
> +{
> + # Create testing interfaces not to interfere with current environment.
> + ip link add dev ${TEST_IF} type veth peer name ${TEST_IF_PEER}
> + ip link set ${TEST_IF} up
> + ip link set ${TEST_IF_PEER} up
> +
> + wait_for_ip
> +
> + tc qdisc add dev ${TEST_IF} clsact
> + tc filter add dev ${TEST_IF} egress bpf obj ${BPF_PROG_OBJ} \
> + sec ${BPF_PROG_SECTION} da
> +
> + BPF_PROG_ID=$(tc filter show dev ${TEST_IF} egress | \
> + awk '/ id / {sub(/.* id /, "", $0); print($1)}')
> +}
> +
> +cleanup()
> +{
> + ip link del ${TEST_IF} 2>/dev/null || :
> + ip link del ${TEST_IF_PEER} 2>/dev/null || :
> +}
> +
> +main()
> +{
> + trap cleanup EXIT 2 3 6 15
> + setup
> + ${PROG} ${TEST_IF} ${BPF_PROG_ID}
> +}
> +
> +DIR=$(dirname $0)
> +TEST_IF="test_cgid_1"
> +TEST_IF_PEER="test_cgid_2"
> +MAX_PING_TRIES=5
> +BPF_PROG_OBJ="${DIR}/test_skb_cgroup_id_kern.o"
> +BPF_PROG_SECTION="cgroup_id_logger"
> +BPF_PROG_ID=0
> +PROG="${DIR}/test_skb_cgroup_id_user"
> +
> +main
> diff --git a/tools/testing/selftests/bpf/test_skb_cgroup_id_kern.c b/tools/testing/selftests/bpf/test_skb_cgroup_id_kern.c
> new file mode 100644
> index 000000000000..68cf9829f5a7
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/test_skb_cgroup_id_kern.c
> @@ -0,0 +1,47 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (c) 2018 Facebook
> +
> +#include <linux/bpf.h>
> +#include <linux/pkt_cls.h>
> +
> +#include <string.h>
> +
> +#include "bpf_helpers.h"
> +
> +#define NUM_CGROUP_LEVELS 4
> +
> +struct bpf_map_def SEC("maps") cgroup_ids = {
> + .type = BPF_MAP_TYPE_ARRAY,
> + .key_size = sizeof(__u32),
> + .value_size = sizeof(__u64),
> + .max_entries = NUM_CGROUP_LEVELS,
> +};
> +
> +static __always_inline void log_nth_level(struct __sk_buff *skb, __u32 level)
> +{
> + __u64 id;
> +
> + /* [1] &level passed to external function that may change it, it's
> + * incompatible with loop unroll.
> + */
> + id = bpf_skb_ancestor_cgroup_id(skb, level);
> + bpf_map_update_elem(&cgroup_ids, &level, &id, 0);
> +}
> +
> +SEC("cgroup_id_logger")
> +int log_cgroup_id(struct __sk_buff *skb)
> +{
> + /* Loop unroll can't be used here due to [1]. Unrolling manually.
> + * Number of calls should be in sync with NUM_CGROUP_LEVELS.
> + */
> + log_nth_level(skb, 0);
> + log_nth_level(skb, 1);
> + log_nth_level(skb, 2);
> + log_nth_level(skb, 3);
> +
> + return TC_ACT_OK;
> +}
> +
> +int _version SEC("version") = 1;
> +
> +char _license[] SEC("license") = "GPL";
> diff --git a/tools/testing/selftests/bpf/test_skb_cgroup_id_user.c b/tools/testing/selftests/bpf/test_skb_cgroup_id_user.c
> new file mode 100644
> index 000000000000..c121cc59f314
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/test_skb_cgroup_id_user.c
> @@ -0,0 +1,187 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (c) 2018 Facebook
> +
> +#include <stdlib.h>
> +#include <string.h>
> +#include <unistd.h>
> +
> +#include <arpa/inet.h>
> +#include <net/if.h>
> +#include <netinet/in.h>
> +#include <sys/socket.h>
> +#include <sys/types.h>
> +
> +
> +#include <bpf/bpf.h>
> +#include <bpf/libbpf.h>
> +
> +#include "bpf_rlimit.h"
> +#include "cgroup_helpers.h"
> +
> +#define CGROUP_PATH "/skb_cgroup_test"
> +#define NUM_CGROUP_LEVELS 4
> +
> +/* RFC 4291, Section 2.7.1 */
> +#define LINKLOCAL_MULTICAST "ff02::1"
> +
> +static int mk_dst_addr(const char *ip, const char *iface,
> + struct sockaddr_in6 *dst)
> +{
> + memset(dst, 0, sizeof(*dst));
> +
> + dst->sin6_family = AF_INET6;
> + dst->sin6_port = htons(1025);
> +
> + if (inet_pton(AF_INET6, ip, &dst->sin6_addr) != 1) {
> + log_err("Invalid IPv6: %s", ip);
> + return -1;
> + }
> +
> + dst->sin6_scope_id = if_nametoindex(iface);
> + if (!dst->sin6_scope_id) {
> + log_err("Failed to get index of iface: %s", iface);
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int send_packet(const char *iface)
> +{
> + struct sockaddr_in6 dst;
> + char msg[] = "msg";
> + int err = 0;
> + int fd = -1;
> +
> + if (mk_dst_addr(LINKLOCAL_MULTICAST, iface, &dst))
> + goto err;
> +
> + fd = socket(AF_INET6, SOCK_DGRAM, 0);
> + if (fd == -1) {
> + log_err("Failed to create UDP socket");
> + goto err;
> + }
> +
> + if (sendto(fd, &msg, sizeof(msg), 0, (const struct sockaddr *)&dst,
> + sizeof(dst)) == -1) {
> + log_err("Failed to send datagram");
> + goto err;
> + }
> +
> + goto out;
> +err:
> + err = -1;
> +out:
> + if (fd >= 0)
> + close(fd);
> + return err;
> +}
> +
> +int get_map_fd_by_prog_id(int prog_id)
> +{
> + struct bpf_prog_info info = {};
> + __u32 info_len = sizeof(info);
> + __u32 map_ids[1];
> + int prog_fd = -1;
> + int map_fd = -1;
> +
> + prog_fd = bpf_prog_get_fd_by_id(prog_id);
> + if (prog_fd < 0) {
> + log_err("Failed to get fd by prog id %d", prog_id);
> + goto err;
> + }
> +
> + info.nr_map_ids = 1;
> + info.map_ids = (__u64) (unsigned long) map_ids;
> +
> + if (bpf_obj_get_info_by_fd(prog_fd, &info, &info_len)) {
> + log_err("Failed to get info by prog fd %d", prog_fd);
> + goto err;
> + }
> +
> + if (!info.nr_map_ids) {
> + log_err("No maps found for prog fd %d", prog_fd);
> + goto err;
> + }
> +
> + map_fd = bpf_map_get_fd_by_id(map_ids[0]);
> + if (map_fd < 0)
> + log_err("Failed to get fd by map id %d", map_ids[0]);
> +err:
> + if (prog_fd >= 0)
> + close(prog_fd);
> + return map_fd;
> +}
> +
> +int check_ancestor_cgroup_ids(int prog_id)
> +{
> + __u64 actual_ids[NUM_CGROUP_LEVELS], expected_ids[NUM_CGROUP_LEVELS];
> + __u32 level;
> + int err = 0;
> + int map_fd;
> +
> + expected_ids[0] = 0x100000001; /* root cgroup */
> + expected_ids[1] = get_cgroup_id("");
> + expected_ids[2] = get_cgroup_id(CGROUP_PATH);
> + expected_ids[3] = 0; /* non-existent cgroup */
> +
> + map_fd = get_map_fd_by_prog_id(prog_id);
> + if (map_fd < 0)
> + goto err;
> +
> + for (level = 0; level < NUM_CGROUP_LEVELS; ++level) {
> + if (bpf_map_lookup_elem(map_fd, &level, &actual_ids[level])) {
> + log_err("Failed to lookup key %d", level);
> + goto err;
> + }
> + if (actual_ids[level] != expected_ids[level]) {
> + log_err("%llx (actual) != %llx (expected), level: %u\n",
> + actual_ids[level], expected_ids[level], level);
> + goto err;
> + }
> + }
> +
> + goto out;
> +err:
> + err = -1;
> +out:
> + if (map_fd >= 0)
> + close(map_fd);
> + return err;
> +}
> +
> +int main(int argc, char **argv)
> +{
> + int cgfd = -1;
> + int err = 0;
> +
> + if (argc < 3) {
> + fprintf(stderr, "Usage: %s iface prog_id\n", argv[0]);
> + exit(EXIT_FAILURE);
> + }
> +
> + if (setup_cgroup_environment())
> + goto err;
> +
> + cgfd = create_and_get_cgroup(CGROUP_PATH);
> + if (!cgfd)
> + goto err;
> +
> + if (join_cgroup(CGROUP_PATH))
> + goto err;
> +
> + if (send_packet(argv[1]))
> + goto err;
> +
> + if (check_ancestor_cgroup_ids(atoi(argv[2])))
> + goto err;
> +
> + goto out;
> +err:
> + err = -1;
> +out:
> + close(cgfd);
> + cleanup_cgroup_environment();
> + printf("[%s]\n", err ? "FAIL" : "PASS");
> + return err;
> +}
>
^ permalink raw reply
* Re: [PATCH bpf-next] bpf: decouple btf from seq bpf fs dump and enable more maps
From: Y Song @ 2018-08-12 6:43 UTC (permalink / raw)
To: Daniel Borkmann
Cc: Alexei Starovoitov, netdev, Yonghong Song, Martin KaFai Lau
In-Reply-To: <20180811235917.2969-1-daniel@iogearbox.net>
On Sat, Aug 11, 2018 at 4:59 PM, Daniel Borkmann <daniel@iogearbox.net> wrote:
> Commit a26ca7c982cb ("bpf: btf: Add pretty print support to
> the basic arraymap") and 699c86d6ec21 ("bpf: btf: add pretty
> print for hash/lru_hash maps") enabled support for BTF and
> dumping via BPF fs for array and hash/lru map. However, both
> can be decoupled from each other such that regular BPF maps
> can be supported for attaching BTF key/value information,
> while not all maps necessarily need to dump via map_seq_show_elem()
> callback.
>
> The basic sanity check which is a prerequisite for all maps
> is that key/value size has to match in any case, and some maps
> can have extra checks via map_check_btf() callback, e.g.
> probing certain types or indicating no support in general. With
> that we can also enable retrieving BTF info for per-cpu map
> types and lpm.
>
> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
> Acked-by: Alexei Starovoitov <ast@kernel.org>
Thanks for the fix. Looks good to me.
For bpftool, BTF pretty print support is missing
for per-cpu maps. bpffs print for per-cpu hash/array maps
need to be added as well. Will add them later.
Acked-by: Yonghong Song <yhs@fb.com>
^ permalink raw reply
* Re: [RFC/RFT, net-next, 00/17] net: Convert neighbor tables to per-namespace
From: Vasily Averin @ 2018-08-12 6:46 UTC (permalink / raw)
To: dsahern, netdev
Cc: nikita.leshchenko, roopa, stephen, idosch, jiri, saeedm,
alex.aring, linux-wpan, netfilter-devel, linux-kernel,
David Ahern
In-Reply-To: <20180717120651.15748-1-dsahern@kernel.org>
On 07/17/2018 03:06 PM, dsahern@kernel.org wrote:
> From: David Ahern <dsahern@gmail.com>
>
> Nikita Leshenko reported that neighbor entries in one namespace can
> evict neighbor entries in another. The problem is that the neighbor
> tables have entries across all namespaces without separate accounting
> and with global limits on when to scan for entries to evict.
>
> Resolve by making the neighbor tables for ipv4, ipv6 and decnet per
> namespace and making the accounting and threshold limits per namespace.
Dear David,
I prepared own patch set to fix this problem and found your one.
It looks perfect for me, and I hope David Miller will merge it soon,
however I have found a few drawbacks:
1) I know that if net_device exist it always have correct net reference,
so dev_net(dev) will be always correct.
However I afraid that device reference itself is correct in some places.
For example,
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -376,9 +377,10 @@ mlxsw_sp_span_entry_gretap4_parms(const struct net_device *to_dev,
return mlxsw_sp_span_entry_unoffloadable(sparmsp);
l3edev = mlxsw_sp_span_gretap4_route(to_dev, &saddr.addr4, &gw.addr4);
+ tbl = ipv4_neigh_table(dev_net(l3edev));
return mlxsw_sp_span_entry_tunnel_parms_common(l3edev, saddr, daddr, gw,
tparm.iph.ttl,
- &arp_tbl, sparmsp);
+ tbl, sparmsp);
}
mlxsw_sp_span_entry_tunnel_parms_common() have "if (!edev)" check inside,
so it seems l3edev can be set to NULL here and lead to crash inside dev_net(l3edev).
There are few other suspicious places and I think they should be carefully re-checked.
2) modified arp_net_init() does not check return value neigh_sysctl_register() and lacks correct rollback.
It was acceptable in arp_init, because it was called only once on boot, but now it will be called
for each new net namespace, it can have real chances to fail lead to memory crash/memory corruption.
3) modified neigh_table_init() is called many times per netns but it can panic in case failed memory allocation.
I think it should be reworked to return errors in such cases, its callers should check it and add correct rollbacks.
4) currently neigh_table_clear() always return 0, I think it makes sense to change it to return void.
Thank you,
Vasily Averin
^ permalink raw reply
* your photo needs
From: Jeff @ 2018-08-11 8:55 UTC (permalink / raw)
To: netdev
We would like to check if your photos need editing. We can do it for you.
Our image editing is for web store photos, jewelries images and beauty and
portrait photos etc.
It is including cut out and clipping path , and also retouching if it is
needed.
We can do test on your photos. Just send us a photo we will start to work
on it,
Thanks,
Jeff Allen
^ permalink raw reply
* Re: [PATCH net-next v2 0/2] ip: faster in-order IP fragments
From: David Miller @ 2018-08-12 0:54 UTC (permalink / raw)
To: posk; +Cc: netdev
In-Reply-To: <20180811202725.242498-1-posk@google.com>
From: Peter Oskolkov <posk@google.com>
Date: Sat, 11 Aug 2018 20:27:23 +0000
> Added "Signed-off-by" in v2.
Series applied, thank you.
^ permalink raw reply
* [PATCH bpf-next] bpf: decouple btf from seq bpf fs dump and enable more maps
From: Daniel Borkmann @ 2018-08-11 23:59 UTC (permalink / raw)
To: ast; +Cc: netdev, yhs, kafai, Daniel Borkmann
Commit a26ca7c982cb ("bpf: btf: Add pretty print support to
the basic arraymap") and 699c86d6ec21 ("bpf: btf: add pretty
print for hash/lru_hash maps") enabled support for BTF and
dumping via BPF fs for array and hash/lru map. However, both
can be decoupled from each other such that regular BPF maps
can be supported for attaching BTF key/value information,
while not all maps necessarily need to dump via map_seq_show_elem()
callback.
The basic sanity check which is a prerequisite for all maps
is that key/value size has to match in any case, and some maps
can have extra checks via map_check_btf() callback, e.g.
probing certain types or indicating no support in general. With
that we can also enable retrieving BTF info for per-cpu map
types and lpm.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
include/linux/bpf.h | 13 +++++++++----
kernel/bpf/arraymap.c | 26 ++++++++++++--------------
kernel/bpf/cpumap.c | 1 +
kernel/bpf/devmap.c | 1 +
kernel/bpf/hashtab.c | 20 +-------------------
kernel/bpf/inode.c | 3 ++-
kernel/bpf/local_storage.c | 1 +
kernel/bpf/lpm_trie.c | 12 ++++++++++++
kernel/bpf/sockmap.c | 2 ++
kernel/bpf/stackmap.c | 1 +
kernel/bpf/syscall.c | 36 ++++++++++++++++++++++++++++++++----
kernel/bpf/xskmap.c | 3 +--
12 files changed, 75 insertions(+), 44 deletions(-)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index db11662..523481a 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -23,7 +23,7 @@ struct bpf_prog;
struct bpf_map;
struct sock;
struct seq_file;
-struct btf;
+struct btf_type;
/* map is generic key/value storage optionally accesible by eBPF programs */
struct bpf_map_ops {
@@ -48,8 +48,9 @@ struct bpf_map_ops {
u32 (*map_fd_sys_lookup_elem)(void *ptr);
void (*map_seq_show_elem)(struct bpf_map *map, void *key,
struct seq_file *m);
- int (*map_check_btf)(const struct bpf_map *map, const struct btf *btf,
- u32 key_type_id, u32 value_type_id);
+ int (*map_check_btf)(const struct bpf_map *map,
+ const struct btf_type *key_type,
+ const struct btf_type *value_type);
};
struct bpf_map {
@@ -118,9 +119,13 @@ static inline bool bpf_map_offload_neutral(const struct bpf_map *map)
static inline bool bpf_map_support_seq_show(const struct bpf_map *map)
{
- return map->ops->map_seq_show_elem && map->ops->map_check_btf;
+ return map->btf && map->ops->map_seq_show_elem;
}
+int map_check_no_btf(const struct bpf_map *map,
+ const struct btf_type *key_type,
+ const struct btf_type *value_type);
+
extern const struct bpf_map_ops bpf_map_offload_ops;
/* function argument constraints */
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index f6ca3e7..0c17aab 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -358,27 +358,20 @@ static void array_map_seq_show_elem(struct bpf_map *map, void *key,
rcu_read_unlock();
}
-static int array_map_check_btf(const struct bpf_map *map, const struct btf *btf,
- u32 btf_key_id, u32 btf_value_id)
+static int array_map_check_btf(const struct bpf_map *map,
+ const struct btf_type *key_type,
+ const struct btf_type *value_type)
{
- const struct btf_type *key_type, *value_type;
- u32 key_size, value_size;
u32 int_data;
- key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
- if (!key_type || BTF_INFO_KIND(key_type->info) != BTF_KIND_INT)
+ if (BTF_INFO_KIND(key_type->info) != BTF_KIND_INT)
return -EINVAL;
int_data = *(u32 *)(key_type + 1);
- /* bpf array can only take a u32 key. This check makes
- * sure that the btf matches the attr used during map_create.
+ /* bpf array can only take a u32 key. This check makes sure
+ * that the btf matches the attr used during map_create.
*/
- if (BTF_INT_BITS(int_data) != 32 || key_size != 4 ||
- BTF_INT_OFFSET(int_data))
- return -EINVAL;
-
- value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
- if (!value_type || value_size != map->value_size)
+ if (BTF_INT_BITS(int_data) != 32 || BTF_INT_OFFSET(int_data))
return -EINVAL;
return 0;
@@ -405,6 +398,7 @@ const struct bpf_map_ops percpu_array_map_ops = {
.map_lookup_elem = percpu_array_map_lookup_elem,
.map_update_elem = array_map_update_elem,
.map_delete_elem = array_map_delete_elem,
+ .map_check_btf = array_map_check_btf,
};
static int fd_array_map_alloc_check(union bpf_attr *attr)
@@ -546,6 +540,7 @@ const struct bpf_map_ops prog_array_map_ops = {
.map_fd_put_ptr = prog_fd_array_put_ptr,
.map_fd_sys_lookup_elem = prog_fd_array_sys_lookup_elem,
.map_release_uref = bpf_fd_array_map_clear,
+ .map_check_btf = map_check_no_btf,
};
static struct bpf_event_entry *bpf_event_entry_gen(struct file *perf_file,
@@ -634,6 +629,7 @@ const struct bpf_map_ops perf_event_array_map_ops = {
.map_fd_get_ptr = perf_event_fd_array_get_ptr,
.map_fd_put_ptr = perf_event_fd_array_put_ptr,
.map_release = perf_event_fd_array_release,
+ .map_check_btf = map_check_no_btf,
};
#ifdef CONFIG_CGROUPS
@@ -665,6 +661,7 @@ const struct bpf_map_ops cgroup_array_map_ops = {
.map_delete_elem = fd_array_map_delete_elem,
.map_fd_get_ptr = cgroup_fd_array_get_ptr,
.map_fd_put_ptr = cgroup_fd_array_put_ptr,
+ .map_check_btf = map_check_no_btf,
};
#endif
@@ -749,4 +746,5 @@ const struct bpf_map_ops array_of_maps_map_ops = {
.map_fd_put_ptr = bpf_map_fd_put_ptr,
.map_fd_sys_lookup_elem = bpf_map_fd_sys_lookup_elem,
.map_gen_lookup = array_of_map_gen_lookup,
+ .map_check_btf = map_check_no_btf,
};
diff --git a/kernel/bpf/cpumap.c b/kernel/bpf/cpumap.c
index e0918d1..3b49494 100644
--- a/kernel/bpf/cpumap.c
+++ b/kernel/bpf/cpumap.c
@@ -555,6 +555,7 @@ const struct bpf_map_ops cpu_map_ops = {
.map_update_elem = cpu_map_update_elem,
.map_lookup_elem = cpu_map_lookup_elem,
.map_get_next_key = cpu_map_get_next_key,
+ .map_check_btf = map_check_no_btf,
};
static int bq_flush_to_queue(struct bpf_cpu_map_entry *rcpu,
diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c
index d361fc1..a7c6620 100644
--- a/kernel/bpf/devmap.c
+++ b/kernel/bpf/devmap.c
@@ -484,6 +484,7 @@ const struct bpf_map_ops dev_map_ops = {
.map_lookup_elem = dev_map_lookup_elem,
.map_update_elem = dev_map_update_elem,
.map_delete_elem = dev_map_delete_elem,
+ .map_check_btf = map_check_no_btf,
};
static int dev_map_notification(struct notifier_block *notifier,
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index d611004..04b8eda 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -1185,23 +1185,6 @@ static void htab_map_seq_show_elem(struct bpf_map *map, void *key,
rcu_read_unlock();
}
-static int htab_map_check_btf(const struct bpf_map *map, const struct btf *btf,
- u32 btf_key_id, u32 btf_value_id)
-{
- const struct btf_type *key_type, *value_type;
- u32 key_size, value_size;
-
- key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
- if (!key_type || key_size != map->key_size)
- return -EINVAL;
-
- value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
- if (!value_type || value_size != map->value_size)
- return -EINVAL;
-
- return 0;
-}
-
const struct bpf_map_ops htab_map_ops = {
.map_alloc_check = htab_map_alloc_check,
.map_alloc = htab_map_alloc,
@@ -1212,7 +1195,6 @@ const struct bpf_map_ops htab_map_ops = {
.map_delete_elem = htab_map_delete_elem,
.map_gen_lookup = htab_map_gen_lookup,
.map_seq_show_elem = htab_map_seq_show_elem,
- .map_check_btf = htab_map_check_btf,
};
const struct bpf_map_ops htab_lru_map_ops = {
@@ -1225,7 +1207,6 @@ const struct bpf_map_ops htab_lru_map_ops = {
.map_delete_elem = htab_lru_map_delete_elem,
.map_gen_lookup = htab_lru_map_gen_lookup,
.map_seq_show_elem = htab_map_seq_show_elem,
- .map_check_btf = htab_map_check_btf,
};
/* Called from eBPF program */
@@ -1452,4 +1433,5 @@ const struct bpf_map_ops htab_of_maps_map_ops = {
.map_fd_put_ptr = bpf_map_fd_put_ptr,
.map_fd_sys_lookup_elem = bpf_map_fd_sys_lookup_elem,
.map_gen_lookup = htab_of_map_gen_lookup,
+ .map_check_btf = map_check_no_btf,
};
diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
index fc5b103..2ada5e2 100644
--- a/kernel/bpf/inode.c
+++ b/kernel/bpf/inode.c
@@ -334,7 +334,8 @@ static int bpf_mkmap(struct dentry *dentry, umode_t mode, void *arg)
struct bpf_map *map = arg;
return bpf_mkobj_ops(dentry, mode, arg, &bpf_map_iops,
- map->btf ? &bpffs_map_fops : &bpffs_obj_fops);
+ bpf_map_support_seq_show(map) ?
+ &bpffs_map_fops : &bpffs_obj_fops);
}
static struct dentry *
diff --git a/kernel/bpf/local_storage.c b/kernel/bpf/local_storage.c
index fc4e37f..22ad967 100644
--- a/kernel/bpf/local_storage.c
+++ b/kernel/bpf/local_storage.c
@@ -246,6 +246,7 @@ const struct bpf_map_ops cgroup_storage_map_ops = {
.map_lookup_elem = cgroup_storage_lookup_elem,
.map_update_elem = cgroup_storage_update_elem,
.map_delete_elem = cgroup_storage_delete_elem,
+ .map_check_btf = map_check_no_btf,
};
int bpf_cgroup_storage_assign(struct bpf_prog *prog, struct bpf_map *_map)
diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c
index 1603492..9058317 100644
--- a/kernel/bpf/lpm_trie.c
+++ b/kernel/bpf/lpm_trie.c
@@ -10,11 +10,13 @@
*/
#include <linux/bpf.h>
+#include <linux/btf.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/vmalloc.h>
#include <net/ipv6.h>
+#include <uapi/linux/btf.h>
/* Intermediate node */
#define LPM_TREE_NODE_FLAG_IM BIT(0)
@@ -686,6 +688,15 @@ static int trie_get_next_key(struct bpf_map *map, void *_key, void *_next_key)
return err;
}
+static int trie_check_btf(const struct bpf_map *map,
+ const struct btf_type *key_type,
+ const struct btf_type *value_type)
+{
+ /* Keys must have struct bpf_lpm_trie_key embedded. */
+ return BTF_INFO_KIND(key_type->info) != BTF_KIND_STRUCT ?
+ -EINVAL : 0;
+}
+
const struct bpf_map_ops trie_map_ops = {
.map_alloc = trie_alloc,
.map_free = trie_free,
@@ -693,4 +704,5 @@ const struct bpf_map_ops trie_map_ops = {
.map_lookup_elem = trie_lookup_elem,
.map_update_elem = trie_update_elem,
.map_delete_elem = trie_delete_elem,
+ .map_check_btf = trie_check_btf,
};
diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c
index 0b38be5..e376fff 100644
--- a/kernel/bpf/sockmap.c
+++ b/kernel/bpf/sockmap.c
@@ -2495,6 +2495,7 @@ const struct bpf_map_ops sock_map_ops = {
.map_update_elem = sock_map_update_elem,
.map_delete_elem = sock_map_delete_elem,
.map_release_uref = sock_map_release,
+ .map_check_btf = map_check_no_btf,
};
const struct bpf_map_ops sock_hash_ops = {
@@ -2505,6 +2506,7 @@ const struct bpf_map_ops sock_hash_ops = {
.map_update_elem = sock_hash_update_elem,
.map_delete_elem = sock_hash_delete_elem,
.map_release_uref = sock_map_release,
+ .map_check_btf = map_check_no_btf,
};
BPF_CALL_4(bpf_sock_map_update, struct bpf_sock_ops_kern *, bpf_sock,
diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c
index b675a3f..8061a43 100644
--- a/kernel/bpf/stackmap.c
+++ b/kernel/bpf/stackmap.c
@@ -607,6 +607,7 @@ const struct bpf_map_ops stack_map_ops = {
.map_lookup_elem = stack_map_lookup_elem,
.map_update_elem = stack_map_update_elem,
.map_delete_elem = stack_map_delete_elem,
+ .map_check_btf = map_check_no_btf,
};
static int __init stack_map_init(void)
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 57f4d07..43727ed 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -103,6 +103,7 @@ int bpf_check_uarg_tail_zero(void __user *uaddr,
const struct bpf_map_ops bpf_map_offload_ops = {
.map_alloc = bpf_map_offload_map_alloc,
.map_free = bpf_map_offload_map_free,
+ .map_check_btf = map_check_no_btf,
};
static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
@@ -455,6 +456,34 @@ static int bpf_obj_name_cpy(char *dst, const char *src)
return 0;
}
+int map_check_no_btf(const struct bpf_map *map,
+ const struct btf_type *key_type,
+ const struct btf_type *value_type)
+{
+ return -ENOTSUPP;
+}
+
+static int map_check_btf(const struct bpf_map *map, const struct btf *btf,
+ u32 btf_key_id, u32 btf_value_id)
+{
+ const struct btf_type *key_type, *value_type;
+ u32 key_size, value_size;
+ int ret = 0;
+
+ key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
+ if (!key_type || key_size != map->key_size)
+ return -EINVAL;
+
+ value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
+ if (!value_type || value_size != map->value_size)
+ return -EINVAL;
+
+ if (map->ops->map_check_btf)
+ ret = map->ops->map_check_btf(map, key_type, value_type);
+
+ return ret;
+}
+
#define BPF_MAP_CREATE_LAST_FIELD btf_value_type_id
/* called via syscall */
static int map_create(union bpf_attr *attr)
@@ -489,8 +518,7 @@ static int map_create(union bpf_attr *attr)
atomic_set(&map->refcnt, 1);
atomic_set(&map->usercnt, 1);
- if (bpf_map_support_seq_show(map) &&
- (attr->btf_key_type_id || attr->btf_value_type_id)) {
+ if (attr->btf_key_type_id || attr->btf_value_type_id) {
struct btf *btf;
if (!attr->btf_key_type_id || !attr->btf_value_type_id) {
@@ -504,8 +532,8 @@ static int map_create(union bpf_attr *attr)
goto free_map_nouncharge;
}
- err = map->ops->map_check_btf(map, btf, attr->btf_key_type_id,
- attr->btf_value_type_id);
+ err = map_check_btf(map, btf, attr->btf_key_type_id,
+ attr->btf_value_type_id);
if (err) {
btf_put(btf);
goto free_map_nouncharge;
diff --git a/kernel/bpf/xskmap.c b/kernel/bpf/xskmap.c
index b3c5574..4ddf61e1 100644
--- a/kernel/bpf/xskmap.c
+++ b/kernel/bpf/xskmap.c
@@ -227,6 +227,5 @@ const struct bpf_map_ops xsk_map_ops = {
.map_lookup_elem = xsk_map_lookup_elem,
.map_update_elem = xsk_map_update_elem,
.map_delete_elem = xsk_map_delete_elem,
+ .map_check_btf = map_check_no_btf,
};
-
-
--
2.9.5
^ permalink raw reply related
* [net-next:master 1999/2033] drivers//net/virtio_net.c:1916:10: error: implicit declaration of function 'cpumask_next_wrap'; did you mean 'cpumask_next_and'?
From: kbuild test robot @ 2018-08-11 23:11 UTC (permalink / raw)
To: Caleb Raitto; +Cc: kbuild-all, netdev, Willem de Bruijn
[-- Attachment #1: Type: text/plain, Size: 2533 bytes --]
tree: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git master
head: 9a95d9c6429bb58905fdfc95da2e1b7cc3fb55b7
commit: 2ca653d607ce59f2729173a7ea56dbfa6330ec88 [1999/2033] virtio_net: Stripe queue affinities across cores.
config: sh-allyesconfig (attached as .config)
compiler: sh4-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
git checkout 2ca653d607ce59f2729173a7ea56dbfa6330ec88
# save the attached .config to linux build tree
GCC_VERSION=7.2.0 make.cross ARCH=sh
All errors (new ones prefixed by >>):
drivers//net/virtio_net.c: In function 'virtnet_set_affinity':
>> drivers//net/virtio_net.c:1916:10: error: implicit declaration of function 'cpumask_next_wrap'; did you mean 'cpumask_next_and'? [-Werror=implicit-function-declaration]
cpu = cpumask_next_wrap(cpu, cpu_online_mask,
^~~~~~~~~~~~~~~~~
cpumask_next_and
cc1: some warnings being treated as errors
vim +1916 drivers//net/virtio_net.c
1889
1890 static void virtnet_set_affinity(struct virtnet_info *vi)
1891 {
1892 cpumask_var_t mask;
1893 int stragglers;
1894 int group_size;
1895 int i, j, cpu;
1896 int num_cpu;
1897 int stride;
1898
1899 if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) {
1900 virtnet_clean_affinity(vi, -1);
1901 return;
1902 }
1903
1904 num_cpu = num_online_cpus();
1905 stride = max_t(int, num_cpu / vi->curr_queue_pairs, 1);
1906 stragglers = num_cpu >= vi->curr_queue_pairs ?
1907 num_cpu % vi->curr_queue_pairs :
1908 0;
1909 cpu = cpumask_next(-1, cpu_online_mask);
1910
1911 for (i = 0; i < vi->curr_queue_pairs; i++) {
1912 group_size = stride + (i < stragglers ? 1 : 0);
1913
1914 for (j = 0; j < group_size; j++) {
1915 cpumask_set_cpu(cpu, mask);
> 1916 cpu = cpumask_next_wrap(cpu, cpu_online_mask,
1917 nr_cpu_ids, false);
1918 }
1919 virtqueue_set_affinity(vi->rq[i].vq, mask);
1920 virtqueue_set_affinity(vi->sq[i].vq, mask);
1921 __netif_set_xps_queue(vi->dev, cpumask_bits(mask), i, false);
1922 cpumask_clear(mask);
1923 }
1924
1925 vi->affinity_hint_set = true;
1926 free_cpumask_var(mask);
1927 }
1928
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 49014 bytes --]
^ permalink raw reply
* [net-next:master 1999/2033] drivers/net/virtio_net.c:1916:10: error: implicit declaration of function 'cpumask_next_wrap'
From: kbuild test robot @ 2018-08-11 22:29 UTC (permalink / raw)
To: Caleb Raitto; +Cc: kbuild-all, netdev, Willem de Bruijn
[-- Attachment #1: Type: text/plain, Size: 2336 bytes --]
tree: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git master
head: 9a95d9c6429bb58905fdfc95da2e1b7cc3fb55b7
commit: 2ca653d607ce59f2729173a7ea56dbfa6330ec88 [1999/2033] virtio_net: Stripe queue affinities across cores.
config: x86_64-randconfig-s1-08120449 (attached as .config)
compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026
reproduce:
git checkout 2ca653d607ce59f2729173a7ea56dbfa6330ec88
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
drivers/net/virtio_net.c: In function 'virtnet_set_affinity':
>> drivers/net/virtio_net.c:1916:10: error: implicit declaration of function 'cpumask_next_wrap' [-Werror=implicit-function-declaration]
cpu = cpumask_next_wrap(cpu, cpu_online_mask,
^~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
vim +/cpumask_next_wrap +1916 drivers/net/virtio_net.c
1889
1890 static void virtnet_set_affinity(struct virtnet_info *vi)
1891 {
1892 cpumask_var_t mask;
1893 int stragglers;
1894 int group_size;
1895 int i, j, cpu;
1896 int num_cpu;
1897 int stride;
1898
1899 if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) {
1900 virtnet_clean_affinity(vi, -1);
1901 return;
1902 }
1903
1904 num_cpu = num_online_cpus();
1905 stride = max_t(int, num_cpu / vi->curr_queue_pairs, 1);
1906 stragglers = num_cpu >= vi->curr_queue_pairs ?
1907 num_cpu % vi->curr_queue_pairs :
1908 0;
1909 cpu = cpumask_next(-1, cpu_online_mask);
1910
1911 for (i = 0; i < vi->curr_queue_pairs; i++) {
1912 group_size = stride + (i < stragglers ? 1 : 0);
1913
1914 for (j = 0; j < group_size; j++) {
1915 cpumask_set_cpu(cpu, mask);
> 1916 cpu = cpumask_next_wrap(cpu, cpu_online_mask,
1917 nr_cpu_ids, false);
1918 }
1919 virtqueue_set_affinity(vi->rq[i].vq, mask);
1920 virtqueue_set_affinity(vi->sq[i].vq, mask);
1921 __netif_set_xps_queue(vi->dev, cpumask_bits(mask), i, false);
1922 cpumask_clear(mask);
1923 }
1924
1925 vi->affinity_hint_set = true;
1926 free_cpumask_var(mask);
1927 }
1928
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 26618 bytes --]
^ permalink raw reply
* [net-next:master 540/547] drivers/net/ethernet/microchip/lan743x_ethtool.c:558:18: error: 'struct lan743x_ptp' has no member named 'ptp_clock'; did you mean 'tx_ts_lock'?
From: kbuild test robot @ 2018-08-11 22:18 UTC (permalink / raw)
To: Bryan Whitehead; +Cc: kbuild-all, netdev
[-- Attachment #1: Type: text/plain, Size: 3064 bytes --]
tree: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git master
head: 9a95d9c6429bb58905fdfc95da2e1b7cc3fb55b7
commit: 07624df1c9efd4b7f2f6762581587c590b03c7a2 [540/547] lan743x: lan743x: Add PTP support
config: x86_64-randconfig-ne0-08120429 (attached as .config)
compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026
reproduce:
git checkout 07624df1c9efd4b7f2f6762581587c590b03c7a2
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
drivers/net/ethernet/microchip/lan743x_ethtool.c: In function 'lan743x_ethtool_get_ts_info':
>> drivers/net/ethernet/microchip/lan743x_ethtool.c:558:18: error: 'struct lan743x_ptp' has no member named 'ptp_clock'; did you mean 'tx_ts_lock'?
if (adapter->ptp.ptp_clock)
^
drivers/net/ethernet/microchip/lan743x_ethtool.c:559:52: error: 'struct lan743x_ptp' has no member named 'ptp_clock'; did you mean 'tx_ts_lock'?
ts_info->phc_index = ptp_clock_index(adapter->ptp.ptp_clock);
^
--
drivers/net/ethernet/microchip/lan743x_ptp.c: In function 'lan743x_ptp_isr':
>> drivers/net/ethernet/microchip/lan743x_ptp.c:781:26: error: 'struct lan743x_ptp' has no member named 'ptp_clock'; did you mean 'tx_ts_lock'?
ptp_schedule_worker(ptp->ptp_clock, 0);
^~
drivers/net/ethernet/microchip/lan743x_ptp.c: In function 'lan743x_ptp_open':
drivers/net/ethernet/microchip/lan743x_ptp.c:879:6: warning: unused variable 'ret' [-Wunused-variable]
int ret = -ENODEV;
^~~
At top level:
drivers/net/ethernet/microchip/lan743x_ptp.c:63:13: warning: 'lan743x_ptp_tx_ts_enqueue_ts' defined but not used [-Wunused-function]
static void lan743x_ptp_tx_ts_enqueue_ts(struct lan743x_adapter *adapter,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
vim +558 drivers/net/ethernet/microchip/lan743x_ethtool.c
545
546 static int lan743x_ethtool_get_ts_info(struct net_device *netdev,
547 struct ethtool_ts_info *ts_info)
548 {
549 struct lan743x_adapter *adapter = netdev_priv(netdev);
550
551 ts_info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
552 SOF_TIMESTAMPING_RX_SOFTWARE |
553 SOF_TIMESTAMPING_SOFTWARE |
554 SOF_TIMESTAMPING_TX_HARDWARE |
555 SOF_TIMESTAMPING_RX_HARDWARE |
556 SOF_TIMESTAMPING_RAW_HARDWARE;
557
> 558 if (adapter->ptp.ptp_clock)
559 ts_info->phc_index = ptp_clock_index(adapter->ptp.ptp_clock);
560 else
561 ts_info->phc_index = -1;
562
563 ts_info->tx_types = BIT(HWTSTAMP_TX_OFF) |
564 BIT(HWTSTAMP_TX_ON) |
565 BIT(HWTSTAMP_TX_ONESTEP_SYNC);
566 ts_info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
567 BIT(HWTSTAMP_FILTER_ALL);
568 return 0;
569 }
570
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 29434 bytes --]
^ permalink raw reply
* Re: [PATCH net-next] rds: avoid lock hierarchy violation between m_rs_lock and rs_recv_lock
From: David Miller @ 2018-08-11 18:22 UTC (permalink / raw)
To: sowmini.varadhan; +Cc: netdev, rds-devel, santosh.shilimkar
In-Reply-To: <1533761833-106379-1-git-send-email-sowmini.varadhan@oracle.com>
From: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Date: Wed, 8 Aug 2018 13:57:13 -0700
> The following deadlock, reported by syzbot, can occur if CPU0 is in
> rds_send_remove_from_sock() while CPU1 is in rds_clear_recv_queue()
>
> CPU0 CPU1
> ---- ----
> lock(&(&rm->m_rs_lock)->rlock);
> lock(&rs->rs_recv_lock);
> lock(&(&rm->m_rs_lock)->rlock);
> lock(&rs->rs_recv_lock);
>
> The deadlock should be avoided by moving the messages from the
> rs_recv_queue into a tmp_list in rds_clear_recv_queue() under
> the rs_recv_lock, and then dropping the refcnt on the messages
> in the tmp_list (potentially resulting in rds_message_purge())
> after dropping the rs_recv_lock.
>
> The same lock hierarchy violation also exists in rds_still_queued()
> and should be avoided in a similar manner
>
> Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
> Reported-by: syzbot+52140d69ac6dc6b927a9@syzkaller.appspotmail.com
I'm putting this in deferred state for now.
Sowmini, once you and Santosh agree on what exactly to do, please
resubmit.
Thank you.
^ permalink raw reply
* [GIT] Networking
From: David Miller @ 2018-08-11 18:20 UTC (permalink / raw)
To: torvalds; +Cc: akpm, netdev, linux-kernel
Last bit of straggler fixes...
1) Fix btf library licensing to LGPL, from Martin KaFai lau.
2) Fix error handling in bpf sockmap code, from Daniel Borkmann.
3) XDP cpumap teardown handling wrt. execution contexts, from
Jesper Dangaard Brouer.
4) Fix loss of runtime PM on failed vlan add/del, from Ivan
Khoronzhuk.
5) xen-netfront caches skb_shinfo(skb) across a __pskb_pull_tail()
call, which potentially changes the skb's data buffer, and thus
skb_shinfo(). Fix from Juergen Gross.
Please pull, thanks a lot!
The following changes since commit 112cbae26d18e75098d95cc234cfa5059de8d479:
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6 (2018-08-09 10:00:15 -0700)
are available in the Git repository at:
gitolite@ra.kernel.org:/pub/scm/linux/kernel/git/davem/net.git
for you to fetch changes up to d472b3a6cf63cd31cae1ed61930f07e6cd6671b5:
xen/netfront: don't cache skb_shinfo() (2018-08-11 09:41:58 -0700)
----------------------------------------------------------------
Alexei Starovoitov (1):
Merge branch 'sockmap-fixes'
Daniel Borkmann (4):
bpf, sockmap: fix bpf_tcp_sendmsg sock error handling
bpf, sockmap: fix leak in bpf_tcp_sendmsg wait for mem path
bpf, sockmap: fix cork timeout for select due to epipe
Merge branch 'bpf-fix-cpu-and-devmap-teardown'
David S. Miller (2):
Merge git://git.kernel.org/.../bpf/bpf
Merge branch 'cpsw-runtime-pm-fix'
Ivan Khoronzhuk (2):
net: ethernet: ti: cpsw: clear all entries when delete vid
net: ethernet: ti: cpsw: fix runtime_pm while add/kill vlan
Jesper Dangaard Brouer (3):
xdp: fix bug in cpumap teardown code path
samples/bpf: xdp_redirect_cpu adjustment to reproduce teardown race easier
xdp: fix bug in devmap teardown code path
Juergen Gross (1):
xen/netfront: don't cache skb_shinfo()
Martin KaFai Lau (1):
bpf: btf: Change tools/lib/bpf/btf to LGPL
drivers/net/ethernet/ti/cpsw.c | 25 +++++++++++--------------
drivers/net/ethernet/ti/cpsw_ale.c | 2 +-
drivers/net/xen-netfront.c | 8 ++++----
kernel/bpf/cpumap.c | 15 +++++++++------
kernel/bpf/devmap.c | 14 +++++++++-----
kernel/bpf/sockmap.c | 9 ++++++---
samples/bpf/xdp_redirect_cpu_kern.c | 2 +-
samples/bpf/xdp_redirect_cpu_user.c | 4 ++--
tools/lib/bpf/btf.c | 2 +-
tools/lib/bpf/btf.h | 2 +-
tools/testing/selftests/bpf/test_sockmap.c | 2 +-
11 files changed, 46 insertions(+), 39 deletions(-)
^ permalink raw reply
* [PATCH net-next v2 2/2] ip: process in-order fragments efficiently
From: Peter Oskolkov @ 2018-08-11 20:27 UTC (permalink / raw)
To: David Miller, netdev; +Cc: Peter Oskolkov, Eric Dumazet, Florian Westphal
In-Reply-To: <20180811202725.242498-1-posk@google.com>
This patch changes the runtime behavior of IP defrag queue:
incoming in-order fragments are added to the end of the current
list/"run" of in-order fragments at the tail.
On some workloads, UDP stream performance is substantially improved:
RX: ./udp_stream -F 10 -T 2 -l 60
TX: ./udp_stream -c -H <host> -F 10 -T 5 -l 60
with this patchset applied on a 10Gbps receiver:
throughput=9524.18
throughput_units=Mbit/s
upstream (net-next):
throughput=4608.93
throughput_units=Mbit/s
Reported-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Peter Oskolkov <posk@google.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Florian Westphal <fw@strlen.de>
---
net/ipv4/inet_fragment.c | 2 +-
net/ipv4/ip_fragment.c | 110 ++++++++++++++++++++++++---------------
2 files changed, 70 insertions(+), 42 deletions(-)
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
index 6d258a5669e7..bcb11f3a27c0 100644
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -146,7 +146,7 @@ void inet_frag_destroy(struct inet_frag_queue *q)
fp = xp;
} while (fp);
} else {
- sum_truesize = skb_rbtree_purge(&q->rb_fragments);
+ sum_truesize = inet_frag_rbtree_purge(&q->rb_fragments);
}
sum = sum_truesize + f->qsize;
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 26ace9d2d976..88281fbce88c 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -126,8 +126,8 @@ static u8 ip4_frag_ecn(u8 tos)
static struct inet_frags ip4_frags;
-static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
- struct net_device *dev);
+static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
+ struct sk_buff *prev_tail, struct net_device *dev);
static void ip4_frag_init(struct inet_frag_queue *q, const void *a)
@@ -219,7 +219,12 @@ static void ip_expire(struct timer_list *t)
head = skb_rb_first(&qp->q.rb_fragments);
if (!head)
goto out;
- rb_erase(&head->rbnode, &qp->q.rb_fragments);
+ if (FRAG_CB(head)->next_frag)
+ rb_replace_node(&head->rbnode,
+ &FRAG_CB(head)->next_frag->rbnode,
+ &qp->q.rb_fragments);
+ else
+ rb_erase(&head->rbnode, &qp->q.rb_fragments);
memset(&head->rbnode, 0, sizeof(head->rbnode));
barrier();
}
@@ -320,7 +325,7 @@ static int ip_frag_reinit(struct ipq *qp)
return -ETIMEDOUT;
}
- sum_truesize = skb_rbtree_purge(&qp->q.rb_fragments);
+ sum_truesize = inet_frag_rbtree_purge(&qp->q.rb_fragments);
sub_frag_mem_limit(qp->q.net, sum_truesize);
qp->q.flags = 0;
@@ -329,6 +334,7 @@ static int ip_frag_reinit(struct ipq *qp)
qp->q.fragments = NULL;
qp->q.rb_fragments = RB_ROOT;
qp->q.fragments_tail = NULL;
+ qp->q.last_run_head = NULL;
qp->iif = 0;
qp->ecn = 0;
@@ -340,7 +346,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
{
struct net *net = container_of(qp->q.net, struct net, ipv4.frags);
struct rb_node **rbn, *parent;
- struct sk_buff *skb1;
+ struct sk_buff *skb1, *prev_tail;
struct net_device *dev;
unsigned int fragsize;
int flags, offset;
@@ -418,38 +424,41 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
*/
/* Find out where to put this fragment. */
- skb1 = qp->q.fragments_tail;
- if (!skb1) {
- /* This is the first fragment we've received. */
- rb_link_node(&skb->rbnode, NULL, &qp->q.rb_fragments.rb_node);
- qp->q.fragments_tail = skb;
- } else if ((skb1->ip_defrag_offset + skb1->len) < end) {
- /* This is the common/special case: skb goes to the end. */
+ prev_tail = qp->q.fragments_tail;
+ if (!prev_tail)
+ ip4_frag_create_run(&qp->q, skb); /* First fragment. */
+ else if (prev_tail->ip_defrag_offset + prev_tail->len < end) {
+ /* This is the common case: skb goes to the end. */
/* Detect and discard overlaps. */
- if (offset < (skb1->ip_defrag_offset + skb1->len))
+ if (offset < prev_tail->ip_defrag_offset + prev_tail->len)
goto discard_qp;
- /* Insert after skb1. */
- rb_link_node(&skb->rbnode, &skb1->rbnode, &skb1->rbnode.rb_right);
- qp->q.fragments_tail = skb;
+ if (offset == prev_tail->ip_defrag_offset + prev_tail->len)
+ ip4_frag_append_to_last_run(&qp->q, skb);
+ else
+ ip4_frag_create_run(&qp->q, skb);
} else {
- /* Binary search. Note that skb can become the first fragment, but
- * not the last (covered above). */
+ /* Binary search. Note that skb can become the first fragment,
+ * but not the last (covered above).
+ */
rbn = &qp->q.rb_fragments.rb_node;
do {
parent = *rbn;
skb1 = rb_to_skb(parent);
if (end <= skb1->ip_defrag_offset)
rbn = &parent->rb_left;
- else if (offset >= skb1->ip_defrag_offset + skb1->len)
+ else if (offset >= skb1->ip_defrag_offset +
+ FRAG_CB(skb1)->frag_run_len)
rbn = &parent->rb_right;
else /* Found an overlap with skb1. */
goto discard_qp;
} while (*rbn);
/* Here we have parent properly set, and rbn pointing to
- * one of its NULL left/right children. Insert skb. */
+ * one of its NULL left/right children. Insert skb.
+ */
+ ip4_frag_init_run(skb);
rb_link_node(&skb->rbnode, parent, rbn);
+ rb_insert_color(&skb->rbnode, &qp->q.rb_fragments);
}
- rb_insert_color(&skb->rbnode, &qp->q.rb_fragments);
if (dev)
qp->iif = dev->ifindex;
@@ -476,7 +485,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
unsigned long orefdst = skb->_skb_refdst;
skb->_skb_refdst = 0UL;
- err = ip_frag_reasm(qp, skb, dev);
+ err = ip_frag_reasm(qp, skb, prev_tail, dev);
skb->_skb_refdst = orefdst;
return err;
}
@@ -495,7 +504,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
/* Build a new IP datagram from all its fragments. */
static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
- struct net_device *dev)
+ struct sk_buff *prev_tail, struct net_device *dev)
{
struct net *net = container_of(qp->q.net, struct net, ipv4.frags);
struct iphdr *iph;
@@ -519,10 +528,16 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
fp = skb_clone(skb, GFP_ATOMIC);
if (!fp)
goto out_nomem;
- rb_replace_node(&skb->rbnode, &fp->rbnode, &qp->q.rb_fragments);
+ FRAG_CB(fp)->next_frag = FRAG_CB(skb)->next_frag;
+ if (RB_EMPTY_NODE(&skb->rbnode))
+ FRAG_CB(prev_tail)->next_frag = fp;
+ else
+ rb_replace_node(&skb->rbnode, &fp->rbnode,
+ &qp->q.rb_fragments);
if (qp->q.fragments_tail == skb)
qp->q.fragments_tail = fp;
skb_morph(skb, head);
+ FRAG_CB(skb)->next_frag = FRAG_CB(head)->next_frag;
rb_replace_node(&head->rbnode, &skb->rbnode,
&qp->q.rb_fragments);
consume_skb(head);
@@ -558,7 +573,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
for (i = 0; i < skb_shinfo(head)->nr_frags; i++)
plen += skb_frag_size(&skb_shinfo(head)->frags[i]);
clone->len = clone->data_len = head->data_len - plen;
- skb->truesize += clone->truesize;
+ head->truesize += clone->truesize;
clone->csum = 0;
clone->ip_summed = head->ip_summed;
add_frag_mem_limit(qp->q.net, clone->truesize);
@@ -571,24 +586,36 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
skb_push(head, head->data - skb_network_header(head));
/* Traverse the tree in order, to build frag_list. */
+ fp = FRAG_CB(head)->next_frag;
rbn = rb_next(&head->rbnode);
rb_erase(&head->rbnode, &qp->q.rb_fragments);
- while (rbn) {
- struct rb_node *rbnext = rb_next(rbn);
- fp = rb_to_skb(rbn);
- rb_erase(rbn, &qp->q.rb_fragments);
- rbn = rbnext;
- *nextp = fp;
- nextp = &fp->next;
- fp->prev = NULL;
- memset(&fp->rbnode, 0, sizeof(fp->rbnode));
- head->data_len += fp->len;
- head->len += fp->len;
- if (head->ip_summed != fp->ip_summed)
- head->ip_summed = CHECKSUM_NONE;
- else if (head->ip_summed == CHECKSUM_COMPLETE)
- head->csum = csum_add(head->csum, fp->csum);
- head->truesize += fp->truesize;
+ while (rbn || fp) {
+ /* fp points to the next sk_buff in the current run;
+ * rbn points to the next run.
+ */
+ /* Go through the current run. */
+ while (fp) {
+ *nextp = fp;
+ nextp = &fp->next;
+ fp->prev = NULL;
+ memset(&fp->rbnode, 0, sizeof(fp->rbnode));
+ head->data_len += fp->len;
+ head->len += fp->len;
+ if (head->ip_summed != fp->ip_summed)
+ head->ip_summed = CHECKSUM_NONE;
+ else if (head->ip_summed == CHECKSUM_COMPLETE)
+ head->csum = csum_add(head->csum, fp->csum);
+ head->truesize += fp->truesize;
+ fp = FRAG_CB(fp)->next_frag;
+ }
+ /* Move to the next run. */
+ if (rbn) {
+ struct rb_node *rbnext = rb_next(rbn);
+
+ fp = rb_to_skb(rbn);
+ rb_erase(rbn, &qp->q.rb_fragments);
+ rbn = rbnext;
+ }
}
sub_frag_mem_limit(qp->q.net, head->truesize);
@@ -624,6 +651,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
qp->q.fragments = NULL;
qp->q.rb_fragments = RB_ROOT;
qp->q.fragments_tail = NULL;
+ qp->q.last_run_head = NULL;
return 0;
out_nomem:
--
2.18.0.597.ga71716f1ad-goog
^ permalink raw reply related
* [PATCH net-next v2 1/2] ip: add helpers to process in-order fragments faster.
From: Peter Oskolkov @ 2018-08-11 20:27 UTC (permalink / raw)
To: David Miller, netdev; +Cc: Peter Oskolkov, Eric Dumazet, Florian Westphal
In-Reply-To: <20180811202725.242498-1-posk@google.com>
This patch introduces several helper functions/macros that will be
used in the follow-up patch. No runtime changes yet.
The new logic (fully implemented in the second patch) is as follows:
* Nodes in the rb-tree will now contain not single fragments, but lists
of consecutive fragments ("runs").
* At each point in time, the current "active" run at the tail is
maintained/tracked. Fragments that arrive in-order, adjacent
to the previous tail fragment, are added to this tail run without
triggering the re-balancing of the rb-tree.
* If a fragment arrives out of order with the offset _before_ the tail run,
it is inserted into the rb-tree as a single fragment.
* If a fragment arrives after the current tail fragment (with a gap),
it starts a new "tail" run, as is inserted into the rb-tree
at the end as the head of the new run.
skb->cb is used to store additional information
needed here (suggested by Eric Dumazet).
Reported-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Peter Oskolkov <posk@google.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Florian Westphal <fw@strlen.de>
---
include/net/inet_frag.h | 6 ++++
net/ipv4/ip_fragment.c | 73 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+)
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
index b86d14528188..1662cbc0b46b 100644
--- a/include/net/inet_frag.h
+++ b/include/net/inet_frag.h
@@ -57,7 +57,9 @@ struct frag_v6_compare_key {
* @lock: spinlock protecting this frag
* @refcnt: reference count of the queue
* @fragments: received fragments head
+ * @rb_fragments: received fragments rb-tree root
* @fragments_tail: received fragments tail
+ * @last_run_head: the head of the last "run". see ip_fragment.c
* @stamp: timestamp of the last received fragment
* @len: total length of the original datagram
* @meat: length of received fragments so far
@@ -78,6 +80,7 @@ struct inet_frag_queue {
struct sk_buff *fragments; /* Used in IPv6. */
struct rb_root rb_fragments; /* Used in IPv4. */
struct sk_buff *fragments_tail;
+ struct sk_buff *last_run_head;
ktime_t stamp;
int len;
int meat;
@@ -113,6 +116,9 @@ void inet_frag_kill(struct inet_frag_queue *q);
void inet_frag_destroy(struct inet_frag_queue *q);
struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, void *key);
+/* Free all skbs in the queue; return the sum of their truesizes. */
+unsigned int inet_frag_rbtree_purge(struct rb_root *root);
+
static inline void inet_frag_put(struct inet_frag_queue *q)
{
if (refcount_dec_and_test(&q->refcnt))
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 7cb7ed761d8c..26ace9d2d976 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -57,6 +57,57 @@
*/
static const char ip_frag_cache_name[] = "ip4-frags";
+/* Use skb->cb to track consecutive/adjacent fragments coming at
+ * the end of the queue. Nodes in the rb-tree queue will
+ * contain "runs" of one or more adjacent fragments.
+ *
+ * Invariants:
+ * - next_frag is NULL at the tail of a "run";
+ * - the head of a "run" has the sum of all fragment lengths in frag_run_len.
+ */
+struct ipfrag_skb_cb {
+ struct inet_skb_parm h;
+ struct sk_buff *next_frag;
+ int frag_run_len;
+};
+
+#define FRAG_CB(skb) ((struct ipfrag_skb_cb *)((skb)->cb))
+
+static void ip4_frag_init_run(struct sk_buff *skb)
+{
+ BUILD_BUG_ON(sizeof(struct ipfrag_skb_cb) > sizeof(skb->cb));
+
+ FRAG_CB(skb)->next_frag = NULL;
+ FRAG_CB(skb)->frag_run_len = skb->len;
+}
+
+/* Append skb to the last "run". */
+static void ip4_frag_append_to_last_run(struct inet_frag_queue *q,
+ struct sk_buff *skb)
+{
+ RB_CLEAR_NODE(&skb->rbnode);
+ FRAG_CB(skb)->next_frag = NULL;
+
+ FRAG_CB(q->last_run_head)->frag_run_len += skb->len;
+ FRAG_CB(q->fragments_tail)->next_frag = skb;
+ q->fragments_tail = skb;
+}
+
+/* Create a new "run" with the skb. */
+static void ip4_frag_create_run(struct inet_frag_queue *q, struct sk_buff *skb)
+{
+ if (q->last_run_head)
+ rb_link_node(&skb->rbnode, &q->last_run_head->rbnode,
+ &q->last_run_head->rbnode.rb_right);
+ else
+ rb_link_node(&skb->rbnode, NULL, &q->rb_fragments.rb_node);
+ rb_insert_color(&skb->rbnode, &q->rb_fragments);
+
+ ip4_frag_init_run(skb);
+ q->fragments_tail = skb;
+ q->last_run_head = skb;
+}
+
/* Describe an entry in the "incomplete datagrams" queue. */
struct ipq {
struct inet_frag_queue q;
@@ -654,6 +705,28 @@ struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user)
}
EXPORT_SYMBOL(ip_check_defrag);
+unsigned int inet_frag_rbtree_purge(struct rb_root *root)
+{
+ struct rb_node *p = rb_first(root);
+ unsigned int sum = 0;
+
+ while (p) {
+ struct sk_buff *skb = rb_entry(p, struct sk_buff, rbnode);
+
+ p = rb_next(p);
+ rb_erase(&skb->rbnode, root);
+ while (skb) {
+ struct sk_buff *next = FRAG_CB(skb)->next_frag;
+
+ sum += skb->truesize;
+ kfree_skb(skb);
+ skb = next;
+ }
+ }
+ return sum;
+}
+EXPORT_SYMBOL(inet_frag_rbtree_purge);
+
#ifdef CONFIG_SYSCTL
static int dist_min;
--
2.18.0.597.ga71716f1ad-goog
^ 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