Netdev List
 help / color / mirror / Atom feed
* [PATCH V2 net-next 2/8] net: hns3: Add "queue info" query function
From: Salil Mehta @ 2018-11-22 14:09 UTC (permalink / raw)
  To: davem
  Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil, netdev,
	linux-kernel, linuxarm, liuzhongzhu
In-Reply-To: <20181122140948.23504-1-salil.mehta@huawei.com>

From: liuzhongzhu <liuzhongzhu@huawei.com>

Query the queue information of the current NIC
such as BD size, queue header and tail pointer.

This  patch adds support for debugfs command:
echo queue info 1 > cmd

it can  print queue config information...

root@(none)# echo queue info 1 > cmd
hns3 0000:7d:00.0: queue info
hns3 0000:7d:00.0: RX(1) BASE ADD: 0x00000000ffb58000
hns3 0000:7d:00.0: RX(1) RING BD NUM: 127
hns3 0000:7d:00.0: RX(1) RING BD LEN: 2
hns3 0000:7d:00.0: RX(1) RING TAIL: 120
hns3 0000:7d:00.0: RX(1) RING HEAD: 0
hns3 0000:7d:00.0: RX(1) RING FBDNUM: 0
hns3 0000:7d:00.0: RX(1) RING PKTNUM: 0
hns3 0000:7d:00.0: TX(1) BASE ADD: 0x00000000fffd8000
hns3 0000:7d:00.0: TX(1) RING BD NUM: 127
hns3 0000:7d:00.0: TX(1) RING TC: 0
hns3 0000:7d:00.0: TX(1) RING TAIL: 2
hns3 0000:7d:00.0: TX(1) RING HEAD: 2
hns3 0000:7d:00.0: TX(1) RING FBDNUM: 0
hns3 0000:7d:00.0: TX(1) RING OFFSET: 0
hns3 0000:7d:00.0: TX(1) RING PKTNUM: 0
root@(none)#

Signed-off-by: liuzhongzhu <liuzhongzhu@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
 drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c | 122 +++++++++++++++++++++
 1 file changed, 122 insertions(+)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
index 9d9ad11..c0685b3 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
@@ -11,6 +11,120 @@
 
 static struct dentry *hns3_dbgfs_root;
 
+static int hns3_dbg_queue_info(struct hnae3_handle *h, char *cmd_buf)
+{
+	struct hns3_nic_priv *priv = h->priv;
+	struct hns3_nic_ring_data *ring_data;
+	struct hns3_enet_ring *ring;
+	u32 base_add_l, base_add_h;
+	u32 queue_num, queue_max;
+	u32 value, i = 0;
+	int cnt;
+
+	if (!priv->ring_data) {
+		dev_err(&h->pdev->dev, "ring_data is NULL\n");
+		return -EFAULT;
+	}
+
+	queue_max = h->kinfo.num_tqps;
+	cnt = kstrtouint(&cmd_buf[11], 0, &queue_num);
+	if (cnt)
+		queue_num = 0;
+	else
+		queue_max = queue_num + 1;
+
+	dev_info(&h->pdev->dev, "queue info\n");
+
+	if (queue_num >= h->kinfo.num_tqps) {
+		dev_err(&h->pdev->dev,
+			"Queue number(%u) is out of range(%u)\n", queue_num,
+			h->kinfo.num_tqps - 1);
+		return -EINVAL;
+	}
+
+	ring_data = priv->ring_data;
+	for (i = queue_num; i < queue_max; i++) {
+		/* Each cycle needs to determine whether the instance is reset,
+		 * to prevent reference to invalid memory. And need to ensure
+		 * that the following code is executed within 100ms.
+		 */
+		if (test_bit(HNS3_NIC_STATE_INITED, &priv->state) ||
+		    test_bit(HNS3_NIC_STATE_RESETTING, &priv->state))
+			return -EPERM;
+
+		ring = ring_data[i + h->kinfo.num_tqps].ring;
+		base_add_h = readl_relaxed(ring->tqp->io_base +
+					   HNS3_RING_RX_RING_BASEADDR_H_REG);
+		base_add_l = readl_relaxed(ring->tqp->io_base +
+					   HNS3_RING_RX_RING_BASEADDR_L_REG);
+		dev_info(&h->pdev->dev, "RX(%d) BASE ADD: 0x%08x%08x\n", i,
+			 base_add_h, base_add_l);
+
+		value = readl_relaxed(ring->tqp->io_base +
+				      HNS3_RING_RX_RING_BD_NUM_REG);
+		dev_info(&h->pdev->dev, "RX(%d) RING BD NUM: %u\n", i, value);
+
+		value = readl_relaxed(ring->tqp->io_base +
+				      HNS3_RING_RX_RING_BD_LEN_REG);
+		dev_info(&h->pdev->dev, "RX(%d) RING BD LEN: %u\n", i, value);
+
+		value = readl_relaxed(ring->tqp->io_base +
+				      HNS3_RING_RX_RING_TAIL_REG);
+		dev_info(&h->pdev->dev, "RX(%d) RING TAIL: %u\n", i, value);
+
+		value = readl_relaxed(ring->tqp->io_base +
+				      HNS3_RING_RX_RING_HEAD_REG);
+		dev_info(&h->pdev->dev, "RX(%d) RING HEAD: %u\n", i, value);
+
+		value = readl_relaxed(ring->tqp->io_base +
+				      HNS3_RING_RX_RING_FBDNUM_REG);
+		dev_info(&h->pdev->dev, "RX(%d) RING FBDNUM: %u\n", i, value);
+
+		value = readl_relaxed(ring->tqp->io_base +
+				      HNS3_RING_RX_RING_PKTNUM_RECORD_REG);
+		dev_info(&h->pdev->dev, "RX(%d) RING PKTNUM: %u\n", i, value);
+
+		ring = ring_data[i].ring;
+		base_add_h = readl_relaxed(ring->tqp->io_base +
+					   HNS3_RING_TX_RING_BASEADDR_H_REG);
+		base_add_l = readl_relaxed(ring->tqp->io_base +
+					   HNS3_RING_TX_RING_BASEADDR_L_REG);
+		dev_info(&h->pdev->dev, "TX(%d) BASE ADD: 0x%08x%08x\n", i,
+			 base_add_h, base_add_l);
+
+		value = readl_relaxed(ring->tqp->io_base +
+				      HNS3_RING_TX_RING_BD_NUM_REG);
+		dev_info(&h->pdev->dev, "TX(%d) RING BD NUM: %u\n", i, value);
+
+		value = readl_relaxed(ring->tqp->io_base +
+				      HNS3_RING_TX_RING_TC_REG);
+		dev_info(&h->pdev->dev, "TX(%d) RING TC: %u\n", i, value);
+
+		value = readl_relaxed(ring->tqp->io_base +
+				      HNS3_RING_TX_RING_TAIL_REG);
+		dev_info(&h->pdev->dev, "TX(%d) RING TAIL: %u\n", i, value);
+
+		value = readl_relaxed(ring->tqp->io_base +
+				      HNS3_RING_TX_RING_HEAD_REG);
+		dev_info(&h->pdev->dev, "TX(%d) RING HEAD: %u\n", i, value);
+
+		value = readl_relaxed(ring->tqp->io_base +
+				      HNS3_RING_TX_RING_FBDNUM_REG);
+		dev_info(&h->pdev->dev, "TX(%d) RING FBDNUM: %u\n", i, value);
+
+		value = readl_relaxed(ring->tqp->io_base +
+				      HNS3_RING_TX_RING_OFFSET_REG);
+		dev_info(&h->pdev->dev, "TX(%d) RING OFFSET: %u\n", i, value);
+
+		value = readl_relaxed(ring->tqp->io_base +
+				      HNS3_RING_TX_RING_PKTNUM_RECORD_REG);
+		dev_info(&h->pdev->dev, "TX(%d) RING PKTNUM: %u\n\n", i,
+			 value);
+	}
+
+	return 0;
+}
+
 static void hns3_dbg_help(struct hnae3_handle *h)
 {
 	dev_info(&h->pdev->dev, "available commands\n");
@@ -51,6 +165,7 @@ static ssize_t hns3_dbg_cmd_write(struct file *filp, const char __user *buffer,
 				  size_t count, loff_t *ppos)
 {
 	struct hnae3_handle *handle = filp->private_data;
+	struct hns3_nic_priv *priv  = handle->priv;
 	char *cmd_buf, *cmd_buf_tmp;
 	int uncopied_bytes;
 	int ret = 0;
@@ -58,6 +173,11 @@ static ssize_t hns3_dbg_cmd_write(struct file *filp, const char __user *buffer,
 	if (*ppos != 0)
 		return 0;
 
+	/* Judge if the instance is being reset. */
+	if (test_bit(HNS3_NIC_STATE_INITED, &priv->state) ||
+	    test_bit(HNS3_NIC_STATE_RESETTING, &priv->state))
+		return 0;
+
 	cmd_buf = kzalloc(count + 1, GFP_KERNEL);
 	if (!cmd_buf)
 		return count;
@@ -78,6 +198,8 @@ static ssize_t hns3_dbg_cmd_write(struct file *filp, const char __user *buffer,
 
 	if (strncmp(cmd_buf, "help", 4) == 0)
 		hns3_dbg_help(handle);
+	else if (strncmp(cmd_buf, "queue info", 10) == 0)
+		ret = hns3_dbg_queue_info(handle, cmd_buf);
 
 	if (ret)
 		hns3_dbg_help(handle);
-- 
2.7.4

^ permalink raw reply related

* [PATCH V2 net-next 4/8] net: hns3: Add "tc config" info query function
From: Salil Mehta @ 2018-11-22 14:09 UTC (permalink / raw)
  To: davem
  Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil, netdev,
	linux-kernel, linuxarm, liuzhongzhu
In-Reply-To: <20181122140948.23504-1-salil.mehta@huawei.com>

From: liuzhongzhu <liuzhongzhu@huawei.com>

This patch prints tc config information.

debugfs command:
echo dump tc > cmd

Sample Output:
root@(none)# echo dump tc > cmd
hns3 0000:7d:00.0: weight_offset: 14
hns3 0000:7d:00.0: tc(0): no sp mode
hns3 0000:7d:00.0: tc(1): no sp mode
hns3 0000:7d:00.0: tc(2): no sp mode
hns3 0000:7d:00.0: tc(3): no sp mode
hns3 0000:7d:00.0: tc(4): no sp mode
hns3 0000:7d:00.0: tc(5): no sp mode
hns3 0000:7d:00.0: tc(6): no sp mode
hns3 0000:7d:00.0: tc(7): no sp mode
root@(none)#

Signed-off-by: liuzhongzhu <liuzhongzhu@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
 drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c |  1 +
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h |  1 +
 .../ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 40 ++++++++++++++++++++++
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h  |  6 ++++
 4 files changed, 48 insertions(+)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
index 82fe7b9..8acccfb 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
@@ -130,6 +130,7 @@ static void hns3_dbg_help(struct hnae3_handle *h)
 	dev_info(&h->pdev->dev, "available commands\n");
 	dev_info(&h->pdev->dev, "queue info [number]\n");
 	dev_info(&h->pdev->dev, "dump fd tcam\n");
+	dev_info(&h->pdev->dev, "dump tc\n");
 }
 
 static ssize_t hns3_dbg_cmd_read(struct file *filp, char __user *buffer,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index aef044d..2b90410 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -126,6 +126,7 @@ enum hclge_opcode_type {
 	HCLGE_OPC_TM_PRI_SCH_MODE_CFG   = 0x0813,
 	HCLGE_OPC_TM_QS_SCH_MODE_CFG    = 0x0814,
 	HCLGE_OPC_TM_BP_TO_QSET_MAPPING = 0x0815,
+	HCLGE_OPC_ETS_TC_WEIGHT		= 0x0843,
 
 	/* Packet buffer allocate commands */
 	HCLGE_OPC_TX_BUFF_ALLOC		= 0x0901,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
index cf1355b..050b90e 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
@@ -5,8 +5,46 @@
 
 #include "hclge_cmd.h"
 #include "hclge_main.h"
+#include "hclge_tm.h"
 #include "hnae3.h"
 
+static void hclge_title_idx_print(struct hclge_dev *hdev, bool flag, int index,
+				  char *title_buf, char *true_buf,
+				  char *false_buf)
+{
+	if (flag)
+		dev_info(&hdev->pdev->dev, "%s(%d): %s\n", title_buf, index,
+			 true_buf);
+	else
+		dev_info(&hdev->pdev->dev, "%s(%d): %s\n", title_buf, index,
+			 false_buf);
+}
+
+static void hclge_dbg_dump_tc(struct hclge_dev *hdev)
+{
+	struct hclge_ets_tc_weight_cmd *ets_weight;
+	struct hclge_desc desc;
+	int i, ret;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_ETS_TC_WEIGHT, true);
+
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret) {
+		dev_err(&hdev->pdev->dev, "dump tc fail, status is %d.\n", ret);
+		return;
+	}
+
+	ets_weight = (struct hclge_ets_tc_weight_cmd *)desc.data;
+
+	dev_info(&hdev->pdev->dev, "dump tc\n");
+	dev_info(&hdev->pdev->dev, "weight_offset: %u\n",
+		 ets_weight->weight_offset);
+
+	for (i = 0; i < HNAE3_MAX_TC; i++)
+		hclge_title_idx_print(hdev, ets_weight->tc_weight[i], i,
+				      "tc", "no sp mode", "sp mode");
+}
+
 static void hclge_dbg_fd_tcam_read(struct hclge_dev *hdev, u8 stage,
 				   bool sel_x, u32 loc)
 {
@@ -68,6 +106,8 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, char *cmd_buf)
 
 	if (strncmp(cmd_buf, "dump fd tcam", 12) == 0) {
 		hclge_dbg_fd_tcam(hdev);
+	} else if (strncmp(cmd_buf, "dump tc", 7) == 0) {
+		hclge_dbg_dump_tc(hdev);
 	} else {
 		dev_info(&hdev->pdev->dev, "unknown command\n");
 		return -EINVAL;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
index 4bd916a..9c6192c 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
@@ -55,6 +55,12 @@ struct hclge_qs_weight_cmd {
 	u8 dwrr;
 };
 
+struct hclge_ets_tc_weight_cmd {
+	u8 tc_weight[HNAE3_MAX_TC];
+	u8 weight_offset;
+	u8 rsvd[15];
+};
+
 #define HCLGE_TM_SHAP_IR_B_MSK  GENMASK(7, 0)
 #define HCLGE_TM_SHAP_IR_B_LSH	0
 #define HCLGE_TM_SHAP_IR_U_MSK  GENMASK(11, 8)
-- 
2.7.4

^ permalink raw reply related

* [PATCH V2 net-next 5/8] net: hns3: Add "tm config" info query function
From: Salil Mehta @ 2018-11-22 14:09 UTC (permalink / raw)
  To: davem
  Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil, netdev,
	linux-kernel, linuxarm, liuzhongzhu
In-Reply-To: <20181122140948.23504-1-salil.mehta@huawei.com>

From: liuzhongzhu <liuzhongzhu@huawei.com>

This patch prints Transmit Module's Traffic sched
related config information.

debugfs command:
echo dump tm > cmd

Sample output:
root@(none)# echo dump tm > cmd
hns3 0000:7d:00.0: dump tm
hns3 0000:7d:00.0: PG_TO_PRI gp_id: 0
hns3 0000:7d:00.0: PG_TO_PRI map: 0x1
hns3 0000:7d:00.0: QS_TO_PRI qs_id: 0
hns3 0000:7d:00.0: QS_TO_PRI priority: 0
hns3 0000:7d:00.0: QS_TO_PRI link_vld: 1
hns3 0000:7d:00.0: NQ_TO_QS nq_id: 0
hns3 0000:7d:00.0: NQ_TO_QS qset_id: 1024
hns3 0000:7d:00.0: PG pg_id: 0
hns3 0000:7d:00.0: PG dwrr: 100
hns3 0000:7d:00.0: QS qs_id: 0
hns3 0000:7d:00.0: QS dwrr: 100
hns3 0000:7d:00.0: PRI pri_id: 0
hns3 0000:7d:00.0: PRI dwrr: 100
hns3 0000:7d:00.0: PRI_C pri_id: 0
hns3 0000:7d:00.0: PRI_C pri_shapping: 0x2850000
hns3 0000:7d:00.0: PRI_P pri_id: 0
hns3 0000:7d:00.0: PRI_P pri_shapping: 0x2850796
hns3 0000:7d:00.0: PG_C pg_id: 0
hns3 0000:7d:00.0: PG_C pg_shapping: 0x2850000
hns3 0000:7d:00.0: PG_P pg_id: 0
hns3 0000:7d:00.0: PG_P pg_shapping: 0x2850496
hns3 0000:7d:00.0: PORT port_shapping: 0x2850296
hns3 0000:7d:00.0: PG_SCH pg_id: 0
hns3 0000:7d:00.0: PRI_SCH pg_id: 0
hns3 0000:7d:00.0: QS_SCH pg_id: 0
hns3 0000:7d:00.0: BP_TO_QSET pg_id: 0
hns3 0000:7d:00.0: BP_TO_QSET pg_shapping: 0x0
hns3 0000:7d:00.0: BP_TO_QSET qs_bit_map: 0x0
root@(none)#

Signed-off-by: liuzhongzhu <liuzhongzhu@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
 drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c |   1 +
 .../ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 199 +++++++++++++++++++++
 2 files changed, 200 insertions(+)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
index 8acccfb..478c133 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
@@ -131,6 +131,7 @@ static void hns3_dbg_help(struct hnae3_handle *h)
 	dev_info(&h->pdev->dev, "queue info [number]\n");
 	dev_info(&h->pdev->dev, "dump fd tcam\n");
 	dev_info(&h->pdev->dev, "dump tc\n");
+	dev_info(&h->pdev->dev, "dump tm\n");
 }
 
 static ssize_t hns3_dbg_cmd_read(struct file *filp, char __user *buffer,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
index 050b90e..e8f1233 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
@@ -45,6 +45,203 @@ static void hclge_dbg_dump_tc(struct hclge_dev *hdev)
 				      "tc", "no sp mode", "sp mode");
 }
 
+static void hclge_dbg_dump_tm_pg(struct hclge_dev *hdev)
+{
+	struct hclge_port_shapping_cmd *port_shap_cfg_cmd;
+	struct hclge_bp_to_qs_map_cmd *bp_to_qs_map_cmd;
+	struct hclge_pg_shapping_cmd *pg_shap_cfg_cmd;
+	enum hclge_opcode_type cmd;
+	struct hclge_desc desc;
+	int ret;
+
+	cmd = HCLGE_OPC_TM_PG_C_SHAPPING;
+	hclge_cmd_setup_basic_desc(&desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		goto err_tm_pg_cmd_send;
+
+	pg_shap_cfg_cmd = (struct hclge_pg_shapping_cmd *)desc.data;
+	dev_info(&hdev->pdev->dev, "PG_C pg_id: %u\n", pg_shap_cfg_cmd->pg_id);
+	dev_info(&hdev->pdev->dev, "PG_C pg_shapping: 0x%x\n",
+		 pg_shap_cfg_cmd->pg_shapping_para);
+
+	cmd = HCLGE_OPC_TM_PG_P_SHAPPING;
+	hclge_cmd_setup_basic_desc(&desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		goto err_tm_pg_cmd_send;
+
+	pg_shap_cfg_cmd = (struct hclge_pg_shapping_cmd *)desc.data;
+	dev_info(&hdev->pdev->dev, "PG_P pg_id: %u\n", pg_shap_cfg_cmd->pg_id);
+	dev_info(&hdev->pdev->dev, "PG_P pg_shapping: 0x%x\n",
+		 pg_shap_cfg_cmd->pg_shapping_para);
+
+	cmd = HCLGE_OPC_TM_PORT_SHAPPING;
+	hclge_cmd_setup_basic_desc(&desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		goto err_tm_pg_cmd_send;
+
+	port_shap_cfg_cmd = (struct hclge_port_shapping_cmd *)desc.data;
+	dev_info(&hdev->pdev->dev, "PORT port_shapping: 0x%x\n",
+		 port_shap_cfg_cmd->port_shapping_para);
+
+	cmd = HCLGE_OPC_TM_PG_SCH_MODE_CFG;
+	hclge_cmd_setup_basic_desc(&desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		goto err_tm_pg_cmd_send;
+
+	dev_info(&hdev->pdev->dev, "PG_SCH pg_id: %u\n", desc.data[0]);
+
+	cmd = HCLGE_OPC_TM_PRI_SCH_MODE_CFG;
+	hclge_cmd_setup_basic_desc(&desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		goto err_tm_pg_cmd_send;
+
+	dev_info(&hdev->pdev->dev, "PRI_SCH pg_id: %u\n", desc.data[0]);
+
+	cmd = HCLGE_OPC_TM_QS_SCH_MODE_CFG;
+	hclge_cmd_setup_basic_desc(&desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		goto err_tm_pg_cmd_send;
+
+	dev_info(&hdev->pdev->dev, "QS_SCH pg_id: %u\n", desc.data[0]);
+
+	cmd = HCLGE_OPC_TM_BP_TO_QSET_MAPPING;
+	hclge_cmd_setup_basic_desc(&desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		goto err_tm_pg_cmd_send;
+
+	bp_to_qs_map_cmd = (struct hclge_bp_to_qs_map_cmd *)desc.data;
+	dev_info(&hdev->pdev->dev, "BP_TO_QSET pg_id: %u\n",
+		 bp_to_qs_map_cmd->tc_id);
+	dev_info(&hdev->pdev->dev, "BP_TO_QSET pg_shapping: 0x%x\n",
+		 bp_to_qs_map_cmd->qs_group_id);
+	dev_info(&hdev->pdev->dev, "BP_TO_QSET qs_bit_map: 0x%x\n",
+		 bp_to_qs_map_cmd->qs_bit_map);
+	return;
+
+err_tm_pg_cmd_send:
+	dev_err(&hdev->pdev->dev, "dump tm_pg fail(0x%x), status is %d\n",
+		cmd, ret);
+}
+
+static void hclge_dbg_dump_tm(struct hclge_dev *hdev)
+{
+	struct hclge_priority_weight_cmd *priority_weight;
+	struct hclge_pg_to_pri_link_cmd *pg_to_pri_map;
+	struct hclge_qs_to_pri_link_cmd *qs_to_pri_map;
+	struct hclge_nq_to_qs_link_cmd *nq_to_qs_map;
+	struct hclge_pri_shapping_cmd *shap_cfg_cmd;
+	struct hclge_pg_weight_cmd *pg_weight;
+	struct hclge_qs_weight_cmd *qs_weight;
+	enum hclge_opcode_type cmd;
+	struct hclge_desc desc;
+	int ret;
+
+	cmd = HCLGE_OPC_TM_PG_TO_PRI_LINK;
+	hclge_cmd_setup_basic_desc(&desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		goto err_tm_cmd_send;
+
+	pg_to_pri_map = (struct hclge_pg_to_pri_link_cmd *)desc.data;
+	dev_info(&hdev->pdev->dev, "dump tm\n");
+	dev_info(&hdev->pdev->dev, "PG_TO_PRI gp_id: %u\n",
+		 pg_to_pri_map->pg_id);
+	dev_info(&hdev->pdev->dev, "PG_TO_PRI map: 0x%x\n",
+		 pg_to_pri_map->pri_bit_map);
+
+	cmd = HCLGE_OPC_TM_QS_TO_PRI_LINK;
+	hclge_cmd_setup_basic_desc(&desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		goto err_tm_cmd_send;
+
+	qs_to_pri_map = (struct hclge_qs_to_pri_link_cmd *)desc.data;
+	dev_info(&hdev->pdev->dev, "QS_TO_PRI qs_id: %u\n",
+		 qs_to_pri_map->qs_id);
+	dev_info(&hdev->pdev->dev, "QS_TO_PRI priority: %u\n",
+		 qs_to_pri_map->priority);
+	dev_info(&hdev->pdev->dev, "QS_TO_PRI link_vld: %u\n",
+		 qs_to_pri_map->link_vld);
+
+	cmd = HCLGE_OPC_TM_NQ_TO_QS_LINK;
+	hclge_cmd_setup_basic_desc(&desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		goto err_tm_cmd_send;
+
+	nq_to_qs_map = (struct hclge_nq_to_qs_link_cmd *)desc.data;
+	dev_info(&hdev->pdev->dev, "NQ_TO_QS nq_id: %u\n", nq_to_qs_map->nq_id);
+	dev_info(&hdev->pdev->dev, "NQ_TO_QS qset_id: %u\n",
+		 nq_to_qs_map->qset_id);
+
+	cmd = HCLGE_OPC_TM_PG_WEIGHT;
+	hclge_cmd_setup_basic_desc(&desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		goto err_tm_cmd_send;
+
+	pg_weight = (struct hclge_pg_weight_cmd *)desc.data;
+	dev_info(&hdev->pdev->dev, "PG pg_id: %u\n", pg_weight->pg_id);
+	dev_info(&hdev->pdev->dev, "PG dwrr: %u\n", pg_weight->dwrr);
+
+	cmd = HCLGE_OPC_TM_QS_WEIGHT;
+	hclge_cmd_setup_basic_desc(&desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		goto err_tm_cmd_send;
+
+	qs_weight = (struct hclge_qs_weight_cmd *)desc.data;
+	dev_info(&hdev->pdev->dev, "QS qs_id: %u\n", qs_weight->qs_id);
+	dev_info(&hdev->pdev->dev, "QS dwrr: %u\n", qs_weight->dwrr);
+
+	cmd = HCLGE_OPC_TM_PRI_WEIGHT;
+	hclge_cmd_setup_basic_desc(&desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		goto err_tm_cmd_send;
+
+	priority_weight = (struct hclge_priority_weight_cmd *)desc.data;
+	dev_info(&hdev->pdev->dev, "PRI pri_id: %u\n", priority_weight->pri_id);
+	dev_info(&hdev->pdev->dev, "PRI dwrr: %u\n", priority_weight->dwrr);
+
+	cmd = HCLGE_OPC_TM_PRI_C_SHAPPING;
+	hclge_cmd_setup_basic_desc(&desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		goto err_tm_cmd_send;
+
+	shap_cfg_cmd = (struct hclge_pri_shapping_cmd *)desc.data;
+	dev_info(&hdev->pdev->dev, "PRI_C pri_id: %u\n", shap_cfg_cmd->pri_id);
+	dev_info(&hdev->pdev->dev, "PRI_C pri_shapping: 0x%x\n",
+		 shap_cfg_cmd->pri_shapping_para);
+
+	cmd = HCLGE_OPC_TM_PRI_P_SHAPPING;
+	hclge_cmd_setup_basic_desc(&desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		goto err_tm_cmd_send;
+
+	shap_cfg_cmd = (struct hclge_pri_shapping_cmd *)desc.data;
+	dev_info(&hdev->pdev->dev, "PRI_P pri_id: %u\n", shap_cfg_cmd->pri_id);
+	dev_info(&hdev->pdev->dev, "PRI_P pri_shapping: 0x%x\n",
+		 shap_cfg_cmd->pri_shapping_para);
+
+	hclge_dbg_dump_tm_pg(hdev);
+
+	return;
+
+err_tm_cmd_send:
+	dev_err(&hdev->pdev->dev, "dump tm fail(0x%x), status is %d\n",
+		cmd, ret);
+}
+
 static void hclge_dbg_fd_tcam_read(struct hclge_dev *hdev, u8 stage,
 				   bool sel_x, u32 loc)
 {
@@ -108,6 +305,8 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, char *cmd_buf)
 		hclge_dbg_fd_tcam(hdev);
 	} else if (strncmp(cmd_buf, "dump tc", 7) == 0) {
 		hclge_dbg_dump_tc(hdev);
+	} else if (strncmp(cmd_buf, "dump tm", 7) == 0) {
+		hclge_dbg_dump_tm(hdev);
 	} else {
 		dev_info(&hdev->pdev->dev, "unknown command\n");
 		return -EINVAL;
-- 
2.7.4

^ permalink raw reply related

* [PATCH V2 net-next 6/8] net: hns3: Add "qos pause" config info query function
From: Salil Mehta @ 2018-11-22 14:09 UTC (permalink / raw)
  To: davem
  Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil, netdev,
	linux-kernel, linuxarm, liuzhongzhu
In-Reply-To: <20181122140948.23504-1-salil.mehta@huawei.com>

From: liuzhongzhu <liuzhongzhu@huawei.com>

This patch prints qos pause config information.

debugfs command:
echo dump qos pause cfg > cmd

Sample Command:
root@(none)# echo dump qos pause cfg > cmd
hns3 0000:7d:00.0: dump qos pause cfg
hns3 0000:7d:00.0: pause_trans_gap: 0xff
hns3 0000:7d:00.0: pause_trans_time: 0xffff
root@(none)#

Signed-off-by: liuzhongzhu <liuzhongzhu@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
 drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c |  1 +
 .../ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 25 ++++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
index 478c133..6258695 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
@@ -132,6 +132,7 @@ static void hns3_dbg_help(struct hnae3_handle *h)
 	dev_info(&h->pdev->dev, "dump fd tcam\n");
 	dev_info(&h->pdev->dev, "dump tc\n");
 	dev_info(&h->pdev->dev, "dump tm\n");
+	dev_info(&h->pdev->dev, "dump qos pause cfg\n");
 }
 
 static ssize_t hns3_dbg_cmd_read(struct file *filp, char __user *buffer,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
index e8f1233..37b312b 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
@@ -242,6 +242,29 @@ static void hclge_dbg_dump_tm(struct hclge_dev *hdev)
 		cmd, ret);
 }
 
+static void hclge_dbg_dump_qos_pause_cfg(struct hclge_dev *hdev)
+{
+	struct hclge_cfg_pause_param_cmd *pause_param;
+	struct hclge_desc desc;
+	int ret;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_MAC_PARA, true);
+
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret) {
+		dev_err(&hdev->pdev->dev, "dump checksum fail, status is %d.\n",
+			ret);
+		return;
+	}
+
+	pause_param = (struct hclge_cfg_pause_param_cmd *)desc.data;
+	dev_info(&hdev->pdev->dev, "dump qos pause cfg\n");
+	dev_info(&hdev->pdev->dev, "pause_trans_gap: 0x%x\n",
+		 pause_param->pause_trans_gap);
+	dev_info(&hdev->pdev->dev, "pause_trans_time: 0x%x\n",
+		 pause_param->pause_trans_time);
+}
+
 static void hclge_dbg_fd_tcam_read(struct hclge_dev *hdev, u8 stage,
 				   bool sel_x, u32 loc)
 {
@@ -307,6 +330,8 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, char *cmd_buf)
 		hclge_dbg_dump_tc(hdev);
 	} else if (strncmp(cmd_buf, "dump tm", 7) == 0) {
 		hclge_dbg_dump_tm(hdev);
+	} else if (strncmp(cmd_buf, "dump qos pause cfg", 18) == 0) {
+		hclge_dbg_dump_qos_pause_cfg(hdev);
 	} else {
 		dev_info(&hdev->pdev->dev, "unknown command\n");
 		return -EINVAL;
-- 
2.7.4

^ permalink raw reply related

* [PATCH V2 net-next 7/8] net: hns3: Add "qos prio map" info query function
From: Salil Mehta @ 2018-11-22 14:09 UTC (permalink / raw)
  To: davem
  Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil, netdev,
	linux-kernel, linuxarm, liuzhongzhu
In-Reply-To: <20181122140948.23504-1-salil.mehta@huawei.com>

From: liuzhongzhu <liuzhongzhu@huawei.com>

This patch prints qos priority map information.

debugfs command:
echo dump qos pri map > cmd

Sample Command:
root@(none)# echo dump qos pri map > cmd
hns3 0000:7d:00.0: dump qos pri map
hns3 0000:7d:00.0: vlan_to_pri: 0x0
hns3 0000:7d:00.0: pri_0_to_tc: 0x0
hns3 0000:7d:00.0: pri_1_to_tc: 0x0
hns3 0000:7d:00.0: pri_2_to_tc: 0x0
hns3 0000:7d:00.0: pri_3_to_tc: 0x0
hns3 0000:7d:00.0: pri_4_to_tc: 0x0
hns3 0000:7d:00.0: pri_5_to_tc: 0x0
hns3 0000:7d:00.0: pri_6_to_tc: 0x0
hns3 0000:7d:00.0: pri_7_to_tc: 0x0
root@(none)#

Signed-off-by: liuzhongzhu <liuzhongzhu@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
 drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c |  1 +
 .../ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 31 ++++++++++++++++++++++
 .../ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h | 23 ++++++++++++++++
 3 files changed, 55 insertions(+)
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
index 6258695..ce284c8 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
@@ -133,6 +133,7 @@ static void hns3_dbg_help(struct hnae3_handle *h)
 	dev_info(&h->pdev->dev, "dump tc\n");
 	dev_info(&h->pdev->dev, "dump tm\n");
 	dev_info(&h->pdev->dev, "dump qos pause cfg\n");
+	dev_info(&h->pdev->dev, "dump qos pri map\n");
 }
 
 static ssize_t hns3_dbg_cmd_read(struct file *filp, char __user *buffer,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
index 37b312b..477acf7 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
@@ -3,6 +3,7 @@
 
 #include <linux/device.h>
 
+#include "hclge_debugfs.h"
 #include "hclge_cmd.h"
 #include "hclge_main.h"
 #include "hclge_tm.h"
@@ -265,6 +266,34 @@ static void hclge_dbg_dump_qos_pause_cfg(struct hclge_dev *hdev)
 		 pause_param->pause_trans_time);
 }
 
+static void hclge_dbg_dump_qos_pri_map(struct hclge_dev *hdev)
+{
+	struct hclge_qos_pri_map_cmd *pri_map;
+	struct hclge_desc desc;
+	int ret;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PRI_TO_TC_MAPPING, true);
+
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"dump qos pri map fail, status is %d.\n", ret);
+		return;
+	}
+
+	pri_map = (struct hclge_qos_pri_map_cmd *)desc.data;
+	dev_info(&hdev->pdev->dev, "dump qos pri map\n");
+	dev_info(&hdev->pdev->dev, "vlan_to_pri: 0x%x\n", pri_map->vlan_pri);
+	dev_info(&hdev->pdev->dev, "pri_0_to_tc: 0x%x\n", pri_map->pri0_tc);
+	dev_info(&hdev->pdev->dev, "pri_1_to_tc: 0x%x\n", pri_map->pri1_tc);
+	dev_info(&hdev->pdev->dev, "pri_2_to_tc: 0x%x\n", pri_map->pri2_tc);
+	dev_info(&hdev->pdev->dev, "pri_3_to_tc: 0x%x\n", pri_map->pri3_tc);
+	dev_info(&hdev->pdev->dev, "pri_4_to_tc: 0x%x\n", pri_map->pri4_tc);
+	dev_info(&hdev->pdev->dev, "pri_5_to_tc: 0x%x\n", pri_map->pri5_tc);
+	dev_info(&hdev->pdev->dev, "pri_6_to_tc: 0x%x\n", pri_map->pri6_tc);
+	dev_info(&hdev->pdev->dev, "pri_7_to_tc: 0x%x\n", pri_map->pri7_tc);
+}
+
 static void hclge_dbg_fd_tcam_read(struct hclge_dev *hdev, u8 stage,
 				   bool sel_x, u32 loc)
 {
@@ -332,6 +361,8 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, char *cmd_buf)
 		hclge_dbg_dump_tm(hdev);
 	} else if (strncmp(cmd_buf, "dump qos pause cfg", 18) == 0) {
 		hclge_dbg_dump_qos_pause_cfg(hdev);
+	} else if (strncmp(cmd_buf, "dump qos pri map", 16) == 0) {
+		hclge_dbg_dump_qos_pri_map(hdev);
 	} else {
 		dev_info(&hdev->pdev->dev, "unknown command\n");
 		return -EINVAL;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h
new file mode 100644
index 0000000..50fd0b1
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2018-2019 Hisilicon Limited. */
+
+#ifndef __HCLGE_DEBUGFS_H
+#define __HCLGE_DEBUGFS_H
+
+#pragma pack(1)
+
+struct hclge_qos_pri_map_cmd {
+	u8 pri0_tc  : 4,
+	   pri1_tc  : 4;
+	u8 pri2_tc  : 4,
+	   pri3_tc  : 4;
+	u8 pri4_tc  : 4,
+	   pri5_tc  : 4;
+	u8 pri6_tc  : 4,
+	   pri7_tc  : 4;
+	u8 vlan_pri : 4,
+	   rev	    : 4;
+};
+
+#pragma pack()
+#endif
-- 
2.7.4

^ permalink raw reply related

* [PATCH V2 net-next 8/8] net: hns3: Add "qos buffer" config info query function
From: Salil Mehta @ 2018-11-22 14:09 UTC (permalink / raw)
  To: davem
  Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil, netdev,
	linux-kernel, linuxarm, liuzhongzhu
In-Reply-To: <20181122140948.23504-1-salil.mehta@huawei.com>

From: liuzhongzhu <liuzhongzhu@huawei.com>

This patch prints qos buffer config information.

debugfs command:
echo dump qos buf cfg > cmd

Sample Command:
root@(none)# echo dump qos buf cfg > cmd
hns3 0000:7d:00.0: dump qos buf cfg
hns3 0000:7d:00.0: tx_packet_buf_tc_0: 0x1aa
hns3 0000:7d:00.0: tx_packet_buf_tc_1: 0x0
hns3 0000:7d:00.0: tx_packet_buf_tc_2: 0x0
hns3 0000:7d:00.0: tx_packet_buf_tc_3: 0x0
hns3 0000:7d:00.0: tx_packet_buf_tc_4: 0x0
hns3 0000:7d:00.0: tx_packet_buf_tc_5: 0x0
hns3 0000:7d:00.0: tx_packet_buf_tc_6: 0x0
hns3 0000:7d:00.0: tx_packet_buf_tc_7: 0x0
hns3 0000:7d:00.0:
hns3 0000:7d:00.0: rx_packet_buf_tc_0: 0x130
hns3 0000:7d:00.0: rx_packet_buf_tc_1: 0x0
hns3 0000:7d:00.0: rx_packet_buf_tc_2: 0x0
hns3 0000:7d:00.0: rx_packet_buf_tc_3: 0x0
hns3 0000:7d:00.0: rx_packet_buf_tc_4: 0x0
hns3 0000:7d:00.0: rx_packet_buf_tc_5: 0x0
hns3 0000:7d:00.0: rx_packet_buf_tc_6: 0x0
hns3 0000:7d:00.0: rx_packet_buf_tc_7: 0x0
hns3 0000:7d:00.0: rx_share_buf: 0x1e0e
root@(none)#

Signed-off-by: liuzhongzhu <liuzhongzhu@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
 drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c |   1 +
 .../ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 115 +++++++++++++++++++++
 2 files changed, 116 insertions(+)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
index ce284c8..86d667a 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
@@ -134,6 +134,7 @@ static void hns3_dbg_help(struct hnae3_handle *h)
 	dev_info(&h->pdev->dev, "dump tm\n");
 	dev_info(&h->pdev->dev, "dump qos pause cfg\n");
 	dev_info(&h->pdev->dev, "dump qos pri map\n");
+	dev_info(&h->pdev->dev, "dump qos buf cfg\n");
 }
 
 static ssize_t hns3_dbg_cmd_read(struct file *filp, char __user *buffer,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
index 477acf7..14577bb 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
@@ -294,6 +294,119 @@ static void hclge_dbg_dump_qos_pri_map(struct hclge_dev *hdev)
 	dev_info(&hdev->pdev->dev, "pri_7_to_tc: 0x%x\n", pri_map->pri7_tc);
 }
 
+static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev)
+{
+	struct hclge_tx_buff_alloc_cmd *tx_buf_cmd;
+	struct hclge_rx_priv_buff_cmd *rx_buf_cmd;
+	struct hclge_rx_priv_wl_buf *rx_priv_wl;
+	struct hclge_rx_com_wl *rx_packet_cnt;
+	struct hclge_rx_com_thrd *rx_com_thrd;
+	struct hclge_rx_com_wl *rx_com_wl;
+	enum hclge_opcode_type cmd;
+	struct hclge_desc desc[2];
+	int i, ret;
+
+	cmd = HCLGE_OPC_TX_BUFF_ALLOC;
+	hclge_cmd_setup_basic_desc(desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, desc, 1);
+	if (ret)
+		goto err_qos_cmd_send;
+
+	dev_info(&hdev->pdev->dev, "dump qos buf cfg\n");
+
+	tx_buf_cmd = (struct hclge_tx_buff_alloc_cmd *)desc[0].data;
+	for (i = 0; i < HCLGE_TC_NUM; i++)
+		dev_info(&hdev->pdev->dev, "tx_packet_buf_tc_%d: 0x%x\n", i,
+			 tx_buf_cmd->tx_pkt_buff[i]);
+
+	cmd = HCLGE_OPC_RX_PRIV_BUFF_ALLOC;
+	hclge_cmd_setup_basic_desc(desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, desc, 1);
+	if (ret)
+		goto err_qos_cmd_send;
+
+	dev_info(&hdev->pdev->dev, "\n");
+	rx_buf_cmd = (struct hclge_rx_priv_buff_cmd *)desc[0].data;
+	for (i = 0; i < HCLGE_TC_NUM; i++)
+		dev_info(&hdev->pdev->dev, "rx_packet_buf_tc_%d: 0x%x\n", i,
+			 rx_buf_cmd->buf_num[i]);
+
+	dev_info(&hdev->pdev->dev, "rx_share_buf: 0x%x\n",
+		 rx_buf_cmd->shared_buf);
+
+	cmd = HCLGE_OPC_RX_PRIV_WL_ALLOC;
+	hclge_cmd_setup_basic_desc(&desc[0], cmd, true);
+	desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT);
+	hclge_cmd_setup_basic_desc(&desc[1], cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, desc, 2);
+	if (ret)
+		goto err_qos_cmd_send;
+
+	dev_info(&hdev->pdev->dev, "\n");
+	rx_priv_wl = (struct hclge_rx_priv_wl_buf *)desc[0].data;
+	for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++)
+		dev_info(&hdev->pdev->dev,
+			 "rx_priv_wl_tc_%d: high: 0x%x, low: 0x%x\n", i,
+			 rx_priv_wl->tc_wl[i].high, rx_priv_wl->tc_wl[i].low);
+
+	rx_priv_wl = (struct hclge_rx_priv_wl_buf *)desc[1].data;
+	for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++)
+		dev_info(&hdev->pdev->dev,
+			 "rx_priv_wl_tc_%d: high: 0x%x, low: 0x%x\n", i + 4,
+			 rx_priv_wl->tc_wl[i].high, rx_priv_wl->tc_wl[i].low);
+
+	cmd = HCLGE_OPC_RX_COM_THRD_ALLOC;
+	hclge_cmd_setup_basic_desc(&desc[0], cmd, true);
+	desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT);
+	hclge_cmd_setup_basic_desc(&desc[1], cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, desc, 2);
+	if (ret)
+		goto err_qos_cmd_send;
+
+	dev_info(&hdev->pdev->dev, "\n");
+	rx_com_thrd = (struct hclge_rx_com_thrd *)desc[0].data;
+	for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++)
+		dev_info(&hdev->pdev->dev,
+			 "rx_com_thrd_tc_%d: high: 0x%x, low: 0x%x\n", i,
+			 rx_com_thrd->com_thrd[i].high,
+			 rx_com_thrd->com_thrd[i].low);
+
+	rx_com_thrd = (struct hclge_rx_com_thrd *)desc[1].data;
+	for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++)
+		dev_info(&hdev->pdev->dev,
+			 "rx_com_thrd_tc_%d: high: 0x%x, low: 0x%x\n", i + 4,
+			 rx_com_thrd->com_thrd[i].high,
+			 rx_com_thrd->com_thrd[i].low);
+
+	cmd = HCLGE_OPC_RX_COM_WL_ALLOC;
+	hclge_cmd_setup_basic_desc(desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, desc, 1);
+	if (ret)
+		goto err_qos_cmd_send;
+
+	rx_com_wl = (struct hclge_rx_com_wl *)desc[0].data;
+	dev_info(&hdev->pdev->dev, "\n");
+	dev_info(&hdev->pdev->dev, "rx_com_wl: high: 0x%x, low: 0x%x\n",
+		 rx_com_wl->com_wl.high, rx_com_wl->com_wl.low);
+
+	cmd = HCLGE_OPC_RX_GBL_PKT_CNT;
+	hclge_cmd_setup_basic_desc(desc, cmd, true);
+	ret = hclge_cmd_send(&hdev->hw, desc, 1);
+	if (ret)
+		goto err_qos_cmd_send;
+
+	rx_packet_cnt = (struct hclge_rx_com_wl *)desc[0].data;
+	dev_info(&hdev->pdev->dev,
+		 "rx_global_packet_cnt: high: 0x%x, low: 0x%x\n",
+		 rx_packet_cnt->com_wl.high, rx_packet_cnt->com_wl.low);
+
+	return;
+
+err_qos_cmd_send:
+	dev_err(&hdev->pdev->dev,
+		"dump qos buf cfg fail(0x%x), status is %d\n", cmd, ret);
+}
+
 static void hclge_dbg_fd_tcam_read(struct hclge_dev *hdev, u8 stage,
 				   bool sel_x, u32 loc)
 {
@@ -363,6 +476,8 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, char *cmd_buf)
 		hclge_dbg_dump_qos_pause_cfg(hdev);
 	} else if (strncmp(cmd_buf, "dump qos pri map", 16) == 0) {
 		hclge_dbg_dump_qos_pri_map(hdev);
+	} else if (strncmp(cmd_buf, "dump qos buf cfg", 16) == 0) {
+		hclge_dbg_dump_qos_buf_cfg(hdev);
 	} else {
 		dev_info(&hdev->pdev->dev, "unknown command\n");
 		return -EINVAL;
-- 
2.7.4

^ permalink raw reply related

* Re: KASAN: use-after-free Read in __lock_sock
From: Marcelo Ricardo Leitner @ 2018-11-22 14:37 UTC (permalink / raw)
  To: Xin Long
  Cc: syzbot+9276d76e83e3bcde6c99, davem, LKML, linux-sctp, network dev,
	Neil Horman, syzkaller-bugs, Vlad Yasevich
In-Reply-To: <CADvbK_f0n64K==prdcM0KzU0S3pbo1oMW3HhE8zMngCUZp3-iQ@mail.gmail.com>

On Thu, Nov 22, 2018 at 10:44:16PM +0900, Xin Long wrote:
> On Thu, Nov 22, 2018 at 10:13 PM Marcelo Ricardo Leitner
> <marcelo.leitner@gmail.com> wrote:
> >
> > On Mon, Nov 19, 2018 at 05:57:33PM +0900, Xin Long wrote:
> > > On Sat, Nov 17, 2018 at 4:18 PM syzbot
> > > <syzbot+9276d76e83e3bcde6c99@syzkaller.appspotmail.com> wrote:
> > > >
> > > > Hello,
> > > >
> > > > syzbot found the following crash on:
> > > >
> > > > HEAD commit:    ccda4af0f4b9 Linux 4.20-rc2
> > > > git tree:       upstream
> > > > console output: https://syzkaller.appspot.com/x/log.txt?x=156cd533400000
> > > > kernel config:  https://syzkaller.appspot.com/x/.config?x=4a0a89f12ca9b0f5
> > > > dashboard link: https://syzkaller.appspot.com/bug?extid=9276d76e83e3bcde6c99
> > > > compiler:       gcc (GCC) 8.0.1 20180413 (experimental)
> > > >
> > > > Unfortunately, I don't have any reproducer for this crash yet.
> > > >
> > > > IMPORTANT: if you fix the bug, please add the following tag to the commit:
> > > > Reported-by: syzbot+9276d76e83e3bcde6c99@syzkaller.appspotmail.com
> > > >
> > > > netlink: 5 bytes leftover after parsing attributes in process
> > > > `syz-executor5'.
> > > > ==================================================================
> > > > BUG: KASAN: use-after-free in __lock_acquire+0x36d9/0x4c20
> > > > kernel/locking/lockdep.c:3218
> > > > Read of size 8 at addr ffff8881d26d60e0 by task syz-executor1/13725
> > > >
> > > > CPU: 0 PID: 13725 Comm: syz-executor1 Not tainted 4.20.0-rc2+ #333
> > > > Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
> > > > Google 01/01/2011
> > > > Call Trace:
> > > >   __dump_stack lib/dump_stack.c:77 [inline]
> > > >   dump_stack+0x244/0x39d lib/dump_stack.c:113
> > > >   print_address_description.cold.7+0x9/0x1ff mm/kasan/report.c:256
> > > >   kasan_report_error mm/kasan/report.c:354 [inline]
> > > >   kasan_report.cold.8+0x242/0x309 mm/kasan/report.c:412
> > > >   __asan_report_load8_noabort+0x14/0x20 mm/kasan/report.c:433
> > > >   __lock_acquire+0x36d9/0x4c20 kernel/locking/lockdep.c:3218
> > > >   lock_acquire+0x1ed/0x520 kernel/locking/lockdep.c:3844
> > > >   __raw_spin_lock_bh include/linux/spinlock_api_smp.h:135 [inline]
> > > >   _raw_spin_lock_bh+0x31/0x40 kernel/locking/spinlock.c:168
> > > >   spin_lock_bh include/linux/spinlock.h:334 [inline]
> > > >   __lock_sock+0x203/0x350 net/core/sock.c:2253
> > > >   lock_sock_nested+0xfe/0x120 net/core/sock.c:2774
> > > >   lock_sock include/net/sock.h:1492 [inline]
> > > >   sctp_sock_dump+0x122/0xb20 net/sctp/diag.c:324
> > >
> > > static int sctp_sock_dump(struct sctp_transport *tsp, void *p)
> > > {
> > >         struct sctp_endpoint *ep = tsp->asoc->ep;
> > >         struct sctp_comm_param *commp = p;
> > >         struct sock *sk = ep->base.sk; <--- [1]
> > > ...
> > >         int err = 0;
> > >
> > >         lock_sock(sk);  <--- [2]
> > >
> > > Between [1] and [2], an asoc peeloff may happen, still thinking
> > > how to avoid this.
> >
> > This race cannot happen more than once for an asoc, so something
> > like this may be doable:
> >
> >         struct sctp_comm_param *commp = p;
> >         struct sctp_endpoint *ep;
> >         struct sock *sk;
> > ...
> >         int err = 0;
> >
> > again:
> >         ep = tsp->asoc->ep;
> >         sk = ep->base.sk; <---[3]
> >         lock_sock(sk);  <--- [2]
> if peel-off happens between [3] and [2], and sk is freed
> somewhere, it will panic on [2] when trying to get the
> sk->lock, no?

Not sure what protects it, but this construct is also used in BH processing at
sctp_rcv():
...
        bh_lock_sock(sk); [4]

        if (sk != rcvr->sk) {
                /* Our cached sk is different from the rcvr->sk.  This is
                 * because migrate()/accept() may have moved the association
                 * to a new socket and released all the sockets.  So now we
                 * are holding a lock on the old socket while the user may
                 * be doing something with the new socket.  Switch our veiw
                 * of the current sk.
                 */
                bh_unlock_sock(sk);
                sk = rcvr->sk;
                bh_lock_sock(sk);
        }
...

If it is not safe, then we have an issue there too.
And by [4] that copy on sk is pretty old already.

> 
> >         if (sk != tsp->asoc->ep->base.sk) {
> >                 /* Asoc was peeloff'd */
> >                 unlock_sock(sk);
> >                 goto again;
> >         }
> >
> > Similarly to what we did on cea0cc80a677 ("sctp: use the right sk
> > after waking up from wait_buf sleep").

^ permalink raw reply

* Re: [net] xfrm_user: use xfrm_state_put to free xfrm_state_alloc return value
From: Herbert Xu @ 2018-11-22 14:43 UTC (permalink / raw)
  To: Mathias Krause
  Cc: Steffen Klassert, Pan Bian, David S. Miller, netdev, linux-kernel,
	Pan Bian
In-Reply-To: <20181121200923.GA12460@jig.fritz.box>

On Wed, Nov 21, 2018 at 09:09:23PM +0100, Mathias Krause wrote:
> 
> -- >8 --
> 
> Subject: [PATCH] xfrm_user: fix freeing of xfrm states on acquire
> 
> Commit 565f0fa902b6 ("xfrm: use a dedicated slab cache for struct
> xfrm_state") moved xfrm state objects to use their own slab cache.
> However, it missed to adapt xfrm_user to use this new cache when
> freeing xfrm states.
> 
> Fix this by introducing and make use of a new helper for freeing
> xfrm_state objects.
> 
> Fixes: 565f0fa902b6 ("xfrm: use a dedicated slab cache for struct xfrm_state")
> Reported-by: Pan Bian <bianpan2016@163.com>
> Cc: <stable@vger.kernel.org> # v4.18+
> Signed-off-by: Mathias Krause <minipli@googlemail.com>

Acked-by: Herbert Xu <herbert@gondor.apana.org.au>

Looks good to me.  Thanks!
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options
From: Nikolay Aleksandrov @ 2018-11-22  4:29 UTC (permalink / raw)
  To: netdev; +Cc: roopa, andrew, davem, bridge, Nikolay Aleksandrov
In-Reply-To: <20181122042925.8878-1-nikolay@cumulusnetworks.com>

We have been adding many new bridge options, a big number of which are
boolean but still take up netlink attribute ids and waste space in the skb.
Recently we discussed learning from link-local packets[1] and decided
yet another new boolean option will be needed, thus introducing this API
to save some bridge nl space.
The API supports changing the value of multiple boolean options at once
via the br_boolopt_multi struct which has an optmask (which options to
set, bit per opt) and optval (options' new values). Future boolean
options will only be added to the br_boolopt_id enum and then will have
to be handled in br_boolopt_toggle/get. The API will automatically
add the ability to change and export them via netlink, sysfs can use the
single boolopt function versions to do the same. The behaviour with
failing/succeeding is the same as with normal netlink option changing.

If an option requires mapping to internal kernel flag or needs special
configuration to be enabled then it should be handled in
br_boolopt_toggle. It should also be able to retrieve an option's current
state via br_boolopt_get.

[1] https://www.spinics.net/lists/netdev/msg532698.html

Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
---
 include/uapi/linux/if_bridge.h | 18 +++++++++
 include/uapi/linux/if_link.h   |  1 +
 net/bridge/br.c                | 68 ++++++++++++++++++++++++++++++++++
 net/bridge/br_netlink.c        | 17 ++++++++-
 net/bridge/br_private.h        |  6 +++
 net/core/rtnetlink.c           |  2 +-
 6 files changed, 110 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h
index e41eda3c71f1..6dc02c03bdf8 100644
--- a/include/uapi/linux/if_bridge.h
+++ b/include/uapi/linux/if_bridge.h
@@ -292,4 +292,22 @@ struct br_mcast_stats {
 	__u64 mcast_bytes[BR_MCAST_DIR_SIZE];
 	__u64 mcast_packets[BR_MCAST_DIR_SIZE];
 };
+
+/* bridge boolean options
+ * IMPORTANT: if adding a new option do not forget to handle
+ *            it in br_boolopt_toggle/get and bridge sysfs
+ */
+enum br_boolopt_id {
+	BR_BOOLOPT_MAX
+};
+
+/* struct br_boolopt_multi - change multiple bridge boolean options
+ *
+ * @optval: new option values (bit per option)
+ * @optmask: options to change (bit per option)
+ */
+struct br_boolopt_multi {
+	__u32 optval;
+	__u32 optmask;
+};
 #endif /* _UAPI_LINUX_IF_BRIDGE_H */
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index f42c069d81db..d6533828123a 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -288,6 +288,7 @@ enum {
 	IFLA_BR_MCAST_IGMP_VERSION,
 	IFLA_BR_MCAST_MLD_VERSION,
 	IFLA_BR_VLAN_STATS_PER_PORT,
+	IFLA_BR_MULTI_BOOLOPT,
 	__IFLA_BR_MAX,
 };
 
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 360ad66c21e9..290b0adbf6d6 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -175,6 +175,74 @@ static struct notifier_block br_switchdev_notifier = {
 	.notifier_call = br_switchdev_event,
 };
 
+/* br_boolopt_toggle - change user-controlled boolean option
+ *
+ * @br: bridge device
+ * @opt: id of the option to change
+ * @on: new option value
+ *
+ * Changes the value of the respective boolean option to @on taking care of
+ * any internal option value mapping and configuration.
+ */
+int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on)
+{
+	int err = -ENOENT;
+
+	switch (opt) {
+	default:
+		break;
+	}
+
+	return err;
+}
+
+int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt)
+{
+	int optval = 0;
+
+	switch (opt) {
+	default:
+		break;
+	}
+
+	return optval;
+}
+
+int br_boolopt_multi_toggle(struct net_bridge *br,
+			    struct br_boolopt_multi *bm)
+{
+	unsigned long bitmap = bm->optmask;
+	int err = 0;
+	int opt_id;
+
+	for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) {
+		bool on = !!(bm->optval & BIT(opt_id));
+
+		err = br_boolopt_toggle(br, opt_id, on);
+		if (err) {
+			br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n",
+				 opt_id, br_boolopt_get(br, opt_id), on, err);
+			break;
+		}
+	}
+
+	return err;
+}
+
+void br_boolopt_multi_get(const struct net_bridge *br,
+			  struct br_boolopt_multi *bm)
+{
+	u32 optval = 0;
+	int opt_id;
+
+	for (opt_id = 0; opt_id < BR_BOOLOPT_MAX; opt_id++)
+		optval |= (br_boolopt_get(br, opt_id) << opt_id);
+
+	bm->optval = optval;
+	bm->optmask = 0;
+}
+
+/* private bridge options, controlled by the kernel */
 void br_opt_toggle(struct net_bridge *br, enum net_bridge_opts opt, bool on)
 {
 	bool cur = !!br_opt_get(br, opt);
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 3345f1984542..11325dc2e90a 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -1035,6 +1035,8 @@ static const struct nla_policy br_policy[IFLA_BR_MAX + 1] = {
 	[IFLA_BR_MCAST_IGMP_VERSION] = { .type = NLA_U8 },
 	[IFLA_BR_MCAST_MLD_VERSION] = { .type = NLA_U8 },
 	[IFLA_BR_VLAN_STATS_PER_PORT] = { .type = NLA_U8 },
+	[IFLA_BR_MULTI_BOOLOPT] = { .type = NLA_EXACT_LEN,
+				    .len = sizeof(struct br_boolopt_multi) },
 };
 
 static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
@@ -1296,6 +1298,15 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
 	}
 #endif
 
+	if (data[IFLA_BR_MULTI_BOOLOPT]) {
+		struct br_boolopt_multi *bm;
+
+		bm = nla_data(data[IFLA_BR_MULTI_BOOLOPT]);
+		err = br_boolopt_multi_toggle(br, bm);
+		if (err)
+			return err;
+	}
+
 	return 0;
 }
 
@@ -1374,6 +1385,7 @@ static size_t br_get_size(const struct net_device *brdev)
 	       nla_total_size(sizeof(u8)) +     /* IFLA_BR_NF_CALL_IP6TABLES */
 	       nla_total_size(sizeof(u8)) +     /* IFLA_BR_NF_CALL_ARPTABLES */
 #endif
+	       nla_total_size(sizeof(struct br_boolopt_multi)) + /* IFLA_BR_MULTI_BOOLOPT */
 	       0;
 }
 
@@ -1387,6 +1399,7 @@ static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev)
 	u32 stp_enabled = br->stp_enabled;
 	u16 priority = (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1];
 	u8 vlan_enabled = br_vlan_enabled(br->dev);
+	struct br_boolopt_multi bm;
 	u64 clockval;
 
 	clockval = br_timer_value(&br->hello_timer);
@@ -1403,6 +1416,7 @@ static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev)
 	if (nla_put_u64_64bit(skb, IFLA_BR_GC_TIMER, clockval, IFLA_BR_PAD))
 		return -EMSGSIZE;
 
+	br_boolopt_multi_get(br, &bm);
 	if (nla_put_u32(skb, IFLA_BR_FORWARD_DELAY, forward_delay) ||
 	    nla_put_u32(skb, IFLA_BR_HELLO_TIME, hello_time) ||
 	    nla_put_u32(skb, IFLA_BR_MAX_AGE, age_time) ||
@@ -1420,7 +1434,8 @@ static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev)
 	    nla_put_u8(skb, IFLA_BR_TOPOLOGY_CHANGE, br->topology_change) ||
 	    nla_put_u8(skb, IFLA_BR_TOPOLOGY_CHANGE_DETECTED,
 		       br->topology_change_detected) ||
-	    nla_put(skb, IFLA_BR_GROUP_ADDR, ETH_ALEN, br->group_addr))
+	    nla_put(skb, IFLA_BR_GROUP_ADDR, ETH_ALEN, br->group_addr) ||
+	    nla_put(skb, IFLA_BR_MULTI_BOOLOPT, sizeof(bm), &bm))
 		return -EMSGSIZE;
 
 #ifdef CONFIG_BRIDGE_VLAN_FILTERING
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index bc2653738fc3..0f051730ed4f 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -507,6 +507,12 @@ static inline int br_opt_get(const struct net_bridge *br,
 	return test_bit(opt, &br->options);
 }
 
+int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on);
+int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt);
+int br_boolopt_multi_toggle(struct net_bridge *br,
+			    struct br_boolopt_multi *bm);
+void br_boolopt_multi_get(const struct net_bridge *br,
+			  struct br_boolopt_multi *bm);
 void br_opt_toggle(struct net_bridge *br, enum net_bridge_opts opt, bool on);
 
 /* br_device.c */
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 86f2d9cbdae3..a498bb41c9aa 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -59,7 +59,7 @@
 #include <net/rtnetlink.h>
 #include <net/net_namespace.h>
 
-#define RTNL_MAX_TYPE		49
+#define RTNL_MAX_TYPE		50
 #define RTNL_SLAVE_MAX_TYPE	36
 
 struct rtnl_link {
-- 
2.17.2

^ permalink raw reply related

* [PATCH net-next 2/2] net: bridge: add no_linklocal_learn bool option
From: Nikolay Aleksandrov @ 2018-11-22  4:29 UTC (permalink / raw)
  To: netdev; +Cc: roopa, andrew, davem, bridge, Nikolay Aleksandrov
In-Reply-To: <20181122042925.8878-1-nikolay@cumulusnetworks.com>

Use the new boolopt API to add an option which disables learning from
link-local packets. The default is kept as before and learning is
enabled. This is a simple map from a boolopt bit to a bridge private
flag that is tested before learning.

Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
---
 include/uapi/linux/if_bridge.h |  3 +++
 net/bridge/br.c                | 10 +++++++---
 net/bridge/br_input.c          |  4 +++-
 net/bridge/br_private.h        |  1 +
 net/bridge/br_sysfs_br.c       | 22 ++++++++++++++++++++++
 5 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h
index 6dc02c03bdf8..773e476a8e54 100644
--- a/include/uapi/linux/if_bridge.h
+++ b/include/uapi/linux/if_bridge.h
@@ -294,10 +294,13 @@ struct br_mcast_stats {
 };
 
 /* bridge boolean options
+ * BR_BOOLOPT_NO_LL_LEARN - disable learning from link-local packets
+ *
  * IMPORTANT: if adding a new option do not forget to handle
  *            it in br_boolopt_toggle/get and bridge sysfs
  */
 enum br_boolopt_id {
+	BR_BOOLOPT_NO_LL_LEARN,
 	BR_BOOLOPT_MAX
 };
 
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 290b0adbf6d6..5b78a6385bd6 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -189,6 +189,10 @@ int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on)
 	int err = -ENOENT;
 
 	switch (opt) {
+	case BR_BOOLOPT_NO_LL_LEARN:
+		err = 0;
+		br_opt_toggle(br, BROPT_NO_LL_LEARN, on);
+		break;
 	default:
 		break;
 	}
@@ -198,14 +202,14 @@ int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on)
 
 int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt)
 {
-	int optval = 0;
-
 	switch (opt) {
+	case BR_BOOLOPT_NO_LL_LEARN:
+		return br_opt_get(br, BROPT_NO_LL_LEARN);
 	default:
 		break;
 	}
 
-	return optval;
+	return 0;
 }
 
 int br_boolopt_multi_toggle(struct net_bridge *br,
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 3ddca11f44c2..5ea7e56119c1 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -188,7 +188,9 @@ static void __br_handle_local_finish(struct sk_buff *skb)
 	u16 vid = 0;
 
 	/* check if vlan is allowed, to avoid spoofing */
-	if (p->flags & BR_LEARNING && br_should_learn(p, skb, &vid))
+	if ((p->flags & BR_LEARNING) &&
+	    !br_opt_get(p->br, BROPT_NO_LL_LEARN) &&
+	    br_should_learn(p, skb, &vid))
 		br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false);
 }
 
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 0f051730ed4f..390848acff08 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -328,6 +328,7 @@ enum net_bridge_opts {
 	BROPT_NEIGH_SUPPRESS_ENABLED,
 	BROPT_MTU_SET_BY_USER,
 	BROPT_VLAN_STATS_PER_PORT,
+	BROPT_NO_LL_LEARN,
 };
 
 struct net_bridge {
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index 60182bef6341..5a03033ccd27 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -328,6 +328,27 @@ static ssize_t flush_store(struct device *d,
 }
 static DEVICE_ATTR_WO(flush);
 
+static ssize_t no_linklocal_learn_show(struct device *d,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	struct net_bridge *br = to_bridge(d);
+	return sprintf(buf, "%d\n", br_boolopt_get(br, BR_BOOLOPT_NO_LL_LEARN));
+}
+
+static int set_no_linklocal_learn(struct net_bridge *br, unsigned long val)
+{
+	return br_boolopt_toggle(br, BR_BOOLOPT_NO_LL_LEARN, !!val);
+}
+
+static ssize_t no_linklocal_learn_store(struct device *d,
+					struct device_attribute *attr,
+					const char *buf, size_t len)
+{
+	return store_bridge_parm(d, buf, len, set_no_linklocal_learn);
+}
+static DEVICE_ATTR_RW(no_linklocal_learn);
+
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 static ssize_t multicast_router_show(struct device *d,
 				     struct device_attribute *attr, char *buf)
@@ -841,6 +862,7 @@ static struct attribute *bridge_attrs[] = {
 	&dev_attr_gc_timer.attr,
 	&dev_attr_group_addr.attr,
 	&dev_attr_flush.attr,
+	&dev_attr_no_linklocal_learn.attr,
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 	&dev_attr_multicast_router.attr,
 	&dev_attr_multicast_snooping.attr,
-- 
2.17.2

^ permalink raw reply related

* Re: [v5, PATCH 2/2] dt-binding: mediatek-dwmac: add binding document for MediaTek MT2712 DWMAC
From: Andrew Lunn @ 2018-11-22 15:19 UTC (permalink / raw)
  To: Biao Huang
  Cc: davem, robh+dt, honghui.zhang, yt.shen, liguo.zhang, mark.rutland,
	nelson.chang, matthias.bgg, netdev, devicetree, linux-kernel,
	linux-arm-kernel, linux-mediatek, joabreu
In-Reply-To: <1542882521-18874-3-git-send-email-biao.huang@mediatek.com>

On Thu, Nov 22, 2018 at 06:28:41PM +0800, Biao Huang wrote:
> The commit adds the device tree binding documentation for the MediaTek DWMAC
> found on MediaTek MT2712.
> 
> Signed-off-by: Biao Huang <biao.huang@mediatek.com>

> +Optional properties:
> +- mediatek,tx-delay: TX clock delay macro value. Range is 0~31. Default is 0.
> +	It should be defined for rgmii/rgmii-rxid/mii interface.
> +- mediatek,rx-delay: RX clock delay macro value. Range is 0~31. Default is 0.
> +	It should be defined for rgmii/rgmii-txid/mii/rmii interface.

You have received the same feedback at least twice now, from two
different maintainers, that the delay should be specified in pS, and
the driver should figure out what values to place into registers.

You should not ignore feedback like that. If you don't understand the
feedback, please ask us to explain it. If you don't agree with the
feedback, you need to argue why you think it is wrong, or why what you
are doing is better, etc.

We are here to help, but just ignoring us won't get you anywhere.

For the moment:

NACK

	Andrew

^ permalink raw reply

* Re: [PATCH net-next,v3 03/12] flow_dissector: add flow action infrastructure
From: Florian Fainelli @ 2018-11-22  4:47 UTC (permalink / raw)
  To: Pablo Neira Ayuso, netdev
  Cc: davem, thomas.lendacky, ariel.elior, michael.chan, santosh,
	madalin.bucur, yisen.zhuang, salil.mehta, jeffrey.t.kirsher,
	tariqt, saeedm, jiri, idosch, jakub.kicinski, peppe.cavallaro,
	grygorii.strashko, andrew, vivien.didelot, alexandre.torgue,
	joabreu, linux-net-drivers, ganeshgr, ogerlitz, Manish.Chopra
In-Reply-To: <20181121025132.14305-4-pablo@netfilter.org>



On 11/20/2018 6:51 PM, Pablo Neira Ayuso wrote:
> This new infrastructure defines the nic actions that you can perform
> from existing network drivers. This infrastructure allows us to avoid a
> direct dependency with the native software TC action representation.
> 
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> ---

[snip]

> +#define flow_action_for_each(__i, __act, __actions)			\
> +        for (__i = 0, __act = &(__actions)->entries[0]; __i < (__actions)->num_entries; __act = &(__actions)->entries[++__i])

Post increment is more common in for_each* constructs, any reason why
you are you using a pre increment here?
-- 
Florian

^ permalink raw reply

* Re: [PATCH net-next,v3 10/12] dsa: bcm_sf2: use flow_rule infrastructure
From: Florian Fainelli @ 2018-11-22  4:56 UTC (permalink / raw)
  To: Pablo Neira Ayuso, netdev
  Cc: davem, thomas.lendacky, ariel.elior, michael.chan, santosh,
	madalin.bucur, yisen.zhuang, salil.mehta, jeffrey.t.kirsher,
	tariqt, saeedm, jiri, idosch, jakub.kicinski, peppe.cavallaro,
	grygorii.strashko, andrew, vivien.didelot, alexandre.torgue,
	joabreu, linux-net-drivers, ganeshgr, ogerlitz, Manish.Chopra
In-Reply-To: <20181121025132.14305-11-pablo@netfilter.org>



On 11/20/2018 6:51 PM, Pablo Neira Ayuso wrote:
> Update this driver to use the flow_rule infrastructure, hence we can use
> the same code to populate hardware IR from ethtool_rx_flow and the
> cls_flower interfaces.
> 
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> ---

[snip]

> @@ -398,9 +411,10 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
>  	 * Reserved		[1]
>  	 * UDF_Valid[8]		[0]
>  	 */
> -	core_writel(priv, v4_spec->tos << IPTOS_SHIFT |
> -		    ip_proto << IPPROTO_SHIFT | ip_frag << IP_FRAG_SHIFT |
> -		    udf_upper_bits(num_udf),
> +	core_writel(priv, ip.key->tos << IPTOS_SHIFT |
> +			  basic.key->n_proto << IPPROTO_SHIFT |
> +			  ip_frag << IP_FRAG_SHIFT |
> +			  udf_upper_bits(num_udf),

Can you maintain the alignment of the arguments here?

Every else looked okay, but I need to check the ipv6 structure to make
sure we can access it as 4x32 bits words like we did before.
-- 
Florian

^ permalink raw reply

* Re: [PATCH net-next,v3 09/12] flow_dissector: add basic ethtool_rx_flow_spec to flow_rule structure translator
From: Florian Fainelli @ 2018-11-22  4:57 UTC (permalink / raw)
  To: Pablo Neira Ayuso, netdev
  Cc: davem, thomas.lendacky, ariel.elior, michael.chan, santosh,
	madalin.bucur, yisen.zhuang, salil.mehta, jeffrey.t.kirsher,
	tariqt, saeedm, jiri, idosch, jakub.kicinski, peppe.cavallaro,
	grygorii.strashko, andrew, vivien.didelot, alexandre.torgue,
	joabreu, linux-net-drivers, ganeshgr, ogerlitz, Manish.Chopra
In-Reply-To: <20181121025132.14305-10-pablo@netfilter.org>



On 11/20/2018 6:51 PM, Pablo Neira Ayuso wrote:
> This patch adds a function to translate the ethtool_rx_flow_spec
> structure to the flow_rule representation.
> 
> This allows us to reuse code from the driver side given that both flower
> and ethtool_rx_flow interfaces use the same representation.
> 
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> ---
> v3: Suggested by Jiri Pirko:
>         - Add struct ethtool_rx_flow_rule, keep placeholder to private
>           dissector information.
>     Reported by Manish Chopra:
> 	- Fix incorrect dissector user_keys flags.
> 
>  include/linux/ethtool.h |  10 +++
>  net/core/ethtool.c      | 189 ++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 199 insertions(+)
> 
> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
> index afd9596ce636..99849e0858b2 100644
> --- a/include/linux/ethtool.h
> +++ b/include/linux/ethtool.h
> @@ -400,4 +400,14 @@ struct ethtool_ops {
>  	void	(*get_ethtool_phy_stats)(struct net_device *,
>  					 struct ethtool_stats *, u64 *);
>  };
> +
> +struct ethtool_rx_flow_rule {
> +	struct flow_rule	*rule;
> +	unsigned long		priv[0];
> +};
> +
> +struct ethtool_rx_flow_rule *
> +ethtool_rx_flow_rule_alloc(const struct ethtool_rx_flow_spec *fs);
> +void ethtool_rx_flow_rule_free(struct ethtool_rx_flow_rule *rule);
> +
>  #endif /* _LINUX_ETHTOOL_H */
> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
> index d05402868575..e679d6478371 100644
> --- a/net/core/ethtool.c
> +++ b/net/core/ethtool.c
> @@ -28,6 +28,7 @@
>  #include <linux/sched/signal.h>
>  #include <linux/net.h>
>  #include <net/xdp_sock.h>
> +#include <net/flow_offload.h>
>  
>  /*
>   * Some useful ethtool_ops methods that're device independent.
> @@ -2808,3 +2809,191 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
>  
>  	return rc;
>  }
> +
> +struct ethtool_rx_flow_key {
> +	struct flow_dissector_key_basic			basic;
> +	union {
> +		struct flow_dissector_key_ipv4_addrs	ipv4;
> +		struct flow_dissector_key_ipv6_addrs	ipv6;
> +	};
> +	struct flow_dissector_key_ports			tp;
> +	struct flow_dissector_key_ip			ip;
> +} __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */
> +
> +struct ethtool_rx_flow_match {
> +	struct flow_dissector		dissector;
> +	struct ethtool_rx_flow_key	key;
> +	struct ethtool_rx_flow_key	mask;
> +};
> +
> +struct ethtool_rx_flow_rule *
> +ethtool_rx_flow_rule_alloc(const struct ethtool_rx_flow_spec *fs)

This is more than alloc, it's allocate and map, no reason to split the
two operations AFAICT, but the name could be improved, how about
alloc_from()?

> +{
> +	static struct in6_addr zero_addr = {};
> +	struct ethtool_rx_flow_match *match;
> +	struct ethtool_rx_flow_rule *flow;
> +	struct flow_action_entry *act;
> +
> +	flow = kzalloc(sizeof(struct ethtool_rx_flow_rule) +
> +		       sizeof(struct ethtool_rx_flow_match), GFP_KERNEL);
> +	if (!flow)
> +		return NULL;
> +
> +	/* ethtool_rx supports only one single action per rule. */
> +	flow->rule = flow_rule_alloc(1);
> +	if (!flow->rule) {
> +		kfree(flow);
> +		return NULL;
> +	}
> +
> +	match = (struct ethtool_rx_flow_match *)flow->priv;
> +	flow->rule->match.dissector	= &match->dissector;
> +	flow->rule->match.mask		= &match->mask;
> +	flow->rule->match.key		= &match->key;
> +
> +	match->mask.basic.n_proto = 0xffff;
> +
> +	switch (fs->flow_type & ~FLOW_EXT) {
> +	case TCP_V4_FLOW:
> +	case UDP_V4_FLOW: {
> +		const struct ethtool_tcpip4_spec *v4_spec, *v4_m_spec;
> +
> +		match->key.basic.n_proto = htons(ETH_P_IP);
> +
> +		v4_spec = &fs->h_u.tcp_ip4_spec;
> +		v4_m_spec = &fs->m_u.tcp_ip4_spec;
> +
> +		if (v4_m_spec->ip4src) {
> +			match->key.ipv4.src = v4_spec->ip4src;
> +			match->mask.ipv4.src = v4_m_spec->ip4src;
> +		}
> +		if (v4_m_spec->ip4dst) {
> +			match->key.ipv4.dst = v4_spec->ip4dst;
> +			match->mask.ipv4.dst = v4_m_spec->ip4dst;
> +		}

I got confused a while ago between the ethtool ntuple and nfc semantics,
and I can't remember if the following is true:

- bits set to 1 indicate a match and bit set to 0 indicate a don't care
for nfc
- bits set to 0 indicate a match and bit set to 1 indicate a don't care
for ntuple

Depending on the answer that could mean that this check on a zero
address may have to change.

> +		if (v4_m_spec->ip4src ||
> +		    v4_m_spec->ip4dst) {
> +			match->dissector.used_keys |=
> +				(1 << FLOW_DISSECTOR_KEY_IPV4_ADDRS);

Can you use BIT() here (and likewise for every one below).

[snip]
> +
> +	return flow;

What about the extended fields and non-IP protocols?
-- 
Florian

^ permalink raw reply

* Re: [PATCH net-next,v3 09/12] flow_dissector: add basic ethtool_rx_flow_spec to flow_rule structure translator
From: Florian Fainelli @ 2018-11-22  4:59 UTC (permalink / raw)
  To: Pablo Neira Ayuso, netdev
  Cc: davem, thomas.lendacky, ariel.elior, michael.chan, santosh,
	madalin.bucur, yisen.zhuang, salil.mehta, jeffrey.t.kirsher,
	tariqt, saeedm, jiri, idosch, jakub.kicinski, peppe.cavallaro,
	grygorii.strashko, andrew, vivien.didelot, alexandre.torgue,
	joabreu, linux-net-drivers, ganeshgr, ogerlitz, Manish.Chopra
In-Reply-To: <20181121025132.14305-10-pablo@netfilter.org>



On 11/20/2018 6:51 PM, Pablo Neira Ayuso wrote:
> This patch adds a function to translate the ethtool_rx_flow_spec
> structure to the flow_rule representation.
> 
> This allows us to reuse code from the driver side given that both flower
> and ethtool_rx_flow interfaces use the same representation.
> 
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> ---
> v3: Suggested by Jiri Pirko:
>         - Add struct ethtool_rx_flow_rule, keep placeholder to private
>           dissector information.
>     Reported by Manish Chopra:
> 	- Fix incorrect dissector user_keys flags.
> 
>  include/linux/ethtool.h |  10 +++
>  net/core/ethtool.c      | 189 ++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 199 insertions(+)
> 
> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
> index afd9596ce636..99849e0858b2 100644
> --- a/include/linux/ethtool.h
> +++ b/include/linux/ethtool.h
> @@ -400,4 +400,14 @@ struct ethtool_ops {
>  	void	(*get_ethtool_phy_stats)(struct net_device *,
>  					 struct ethtool_stats *, u64 *);
>  };
> +
> +struct ethtool_rx_flow_rule {
> +	struct flow_rule	*rule;
> +	unsigned long		priv[0];

This forces you to cast to/from that member, any reason this is just not
a void *priv here?
-- 
Florian

^ permalink raw reply

* [PATCH bpf-next 1/1] bpf, lpm: make longest_prefix_match() faster
From: Eric Dumazet @ 2018-11-22  5:22 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Daniel Borkmann, netdev, Eric Dumazet, Eric Dumazet,
	Vlad Dumitrescu

At LPC 2018 in Vancouver, Vlad Dumitrescu mentioned that longest_prefix_match()
has a high cost [1].

One reason for that cost is a loop handling one byte at a time.

We can handle more bytes at a time, if enough attention is paid
to endianness.

I was able to remove ~55 % of longest_prefix_match() cpu costs.

[1] https://linuxplumbersconf.org/event/2/contributions/88/attachments/76/87/lpc-bpf-2018-shaping.pdf

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Vlad Dumitrescu <vladum@google.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Daniel Borkmann <dborkman@redhat.com>
---
 kernel/bpf/lpm_trie.c | 59 +++++++++++++++++++++++++++++++++++--------
 1 file changed, 49 insertions(+), 10 deletions(-)

diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c
index 9058317ba9de2eae4f28e8ca98c3c30bc6167c24..bfd4882e1106c699b62217eef0c2cc92f31077c6 100644
--- a/kernel/bpf/lpm_trie.c
+++ b/kernel/bpf/lpm_trie.c
@@ -168,20 +168,59 @@ static size_t longest_prefix_match(const struct lpm_trie *trie,
 				   const struct lpm_trie_node *node,
 				   const struct bpf_lpm_trie_key *key)
 {
-	size_t prefixlen = 0;
-	size_t i;
+	u32 limit = min(node->prefixlen, key->prefixlen);
+	u32 prefixlen = 0, i = 0;
 
-	for (i = 0; i < trie->data_size; i++) {
-		size_t b;
+	BUILD_BUG_ON(offsetof(struct lpm_trie_node, data) % sizeof(u32));
+	BUILD_BUG_ON(offsetof(struct bpf_lpm_trie_key, data) % sizeof(u32));
 
-		b = 8 - fls(node->data[i] ^ key->data[i]);
-		prefixlen += b;
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(CONFIG_64BIT)
 
-		if (prefixlen >= node->prefixlen || prefixlen >= key->prefixlen)
-			return min(node->prefixlen, key->prefixlen);
+	/* data_size >= 16 has very small probability.
+	 * We do not use a loop for optimal code generation.
+	 */
+	if (trie->data_size >= 8) {
+		u64 diff = be64_to_cpu(*(__be64 *)node->data ^
+				       *(__be64 *)key->data);
 
-		if (b < 8)
-			break;
+		prefixlen = 64 - fls64(diff);
+		if (prefixlen >= limit)
+			return limit;
+		if (diff)
+			return prefixlen;
+		i = 8;
+	}
+#endif
+
+	while (trie->data_size >= i + 4) {
+		u32 diff = be32_to_cpu(*(__be32 *)&node->data[i] ^
+				       *(__be32 *)&key->data[i]);
+
+		prefixlen += 32 - fls(diff);
+		if (prefixlen >= limit)
+			return limit;
+		if (diff)
+			return prefixlen;
+		i += 4;
+	}
+
+	if (trie->data_size >= i + 2) {
+		u16 diff = be16_to_cpu(*(__be16 *)&node->data[i] ^
+				       *(__be16 *)&key->data[i]);
+
+		prefixlen += 16 - fls(diff);
+		if (prefixlen >= limit)
+			return limit;
+		if (diff)
+			return prefixlen;
+		i += 2;
+	}
+
+	if (trie->data_size >= i + 1) {
+		prefixlen += 8 - fls(node->data[i] ^ key->data[i]);
+
+		if (prefixlen >= limit)
+			return limit;
 	}
 
 	return prefixlen;
-- 
2.19.1.1215.g8438c0b245-goog

^ permalink raw reply related

* [PATCH bpf-next v2 1/1] bpf, lpm: make longest_prefix_match() faster
From: Eric Dumazet @ 2018-11-22  5:39 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Daniel Borkmann, netdev, Eric Dumazet, Eric Dumazet,
	Vlad Dumitrescu

At LPC 2018 in Vancouver, Vlad Dumitrescu mentioned that longest_prefix_match()
has a high cost [1].

One reason for that cost is a loop handling one byte at a time.

We can handle more bytes at a time, if enough attention is paid
to endianness.

I was able to remove ~55 % of longest_prefix_match() cpu costs.

[1] https://linuxplumbersconf.org/event/2/contributions/88/attachments/76/87/lpc-bpf-2018-shaping.pdf

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Vlad Dumitrescu <vladum@google.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
---
v2: fixed Daniel and Alexei email addresses... :/

 kernel/bpf/lpm_trie.c | 59 +++++++++++++++++++++++++++++++++++--------
 1 file changed, 49 insertions(+), 10 deletions(-)

diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c
index 9058317ba9de2eae4f28e8ca98c3c30bc6167c24..bfd4882e1106c699b62217eef0c2cc92f31077c6 100644
--- a/kernel/bpf/lpm_trie.c
+++ b/kernel/bpf/lpm_trie.c
@@ -168,20 +168,59 @@ static size_t longest_prefix_match(const struct lpm_trie *trie,
 				   const struct lpm_trie_node *node,
 				   const struct bpf_lpm_trie_key *key)
 {
-	size_t prefixlen = 0;
-	size_t i;
+	u32 limit = min(node->prefixlen, key->prefixlen);
+	u32 prefixlen = 0, i = 0;
 
-	for (i = 0; i < trie->data_size; i++) {
-		size_t b;
+	BUILD_BUG_ON(offsetof(struct lpm_trie_node, data) % sizeof(u32));
+	BUILD_BUG_ON(offsetof(struct bpf_lpm_trie_key, data) % sizeof(u32));
 
-		b = 8 - fls(node->data[i] ^ key->data[i]);
-		prefixlen += b;
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(CONFIG_64BIT)
 
-		if (prefixlen >= node->prefixlen || prefixlen >= key->prefixlen)
-			return min(node->prefixlen, key->prefixlen);
+	/* data_size >= 16 has very small probability.
+	 * We do not use a loop for optimal code generation.
+	 */
+	if (trie->data_size >= 8) {
+		u64 diff = be64_to_cpu(*(__be64 *)node->data ^
+				       *(__be64 *)key->data);
 
-		if (b < 8)
-			break;
+		prefixlen = 64 - fls64(diff);
+		if (prefixlen >= limit)
+			return limit;
+		if (diff)
+			return prefixlen;
+		i = 8;
+	}
+#endif
+
+	while (trie->data_size >= i + 4) {
+		u32 diff = be32_to_cpu(*(__be32 *)&node->data[i] ^
+				       *(__be32 *)&key->data[i]);
+
+		prefixlen += 32 - fls(diff);
+		if (prefixlen >= limit)
+			return limit;
+		if (diff)
+			return prefixlen;
+		i += 4;
+	}
+
+	if (trie->data_size >= i + 2) {
+		u16 diff = be16_to_cpu(*(__be16 *)&node->data[i] ^
+				       *(__be16 *)&key->data[i]);
+
+		prefixlen += 16 - fls(diff);
+		if (prefixlen >= limit)
+			return limit;
+		if (diff)
+			return prefixlen;
+		i += 2;
+	}
+
+	if (trie->data_size >= i + 1) {
+		prefixlen += 8 - fls(node->data[i] ^ key->data[i]);
+
+		if (prefixlen >= limit)
+			return limit;
 	}
 
 	return prefixlen;
-- 
2.19.1.1215.g8438c0b245-goog

^ permalink raw reply related

* [RFC PATCH bpf-next] libbpf: make bpf_object__open default to UNSPEC
From: Nikita V. Shirokov @ 2018-11-22  6:03 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann; +Cc: netdev, Nikita V. Shirokov

currently by default libbpf's bpf_object__open requires
bpf's program to specify  version in a code because of two things:
1) default prog type is set to KPROBE
2) KPROBE requires (in kernel/bpf/syscall.c) version to be specified

in this RFC i'm proposing change default to UNSPEC and also changing
logic of libbpf that it would reflect what we have today in kernel
(aka only KPROBE type requires for version to be explicitly set).

reason for change:
currently only libbpf requires by default version to be
explicitly set. it would be really hard for mainteiners of other custom
bpf loaders to migrate to libbpf (as they dont control user's code
and migration to the new loader (libbpf) wont be transparent for end
user).

what is going to be broken after this change:
if someone were relying on default to be KPROBE for bpf_object__open
his code will stop to work. however i'm really doubtfull that anyone
is using this for kprobe type of programs (instead of, say, bcc or
other tracing frameworks)

other possible solutions (for discussion, would require more machinery):
add another function like bpf_object__open w/ default to unspec

Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
---
 tools/lib/bpf/libbpf.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 0f14f7c074c2..ed4212a4c5f9 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -333,7 +333,7 @@ bpf_program__init(void *data, size_t size, char *section_name, int idx,
 	prog->idx = idx;
 	prog->instances.fds = NULL;
 	prog->instances.nr = -1;
-	prog->type = BPF_PROG_TYPE_KPROBE;
+	prog->type = BPF_PROG_TYPE_UNSPEC;
 	prog->btf_fd = -1;
 
 	return 0;
@@ -1649,12 +1649,12 @@ static bool bpf_prog_type__needs_kver(enum bpf_prog_type type)
 	case BPF_PROG_TYPE_LIRC_MODE2:
 	case BPF_PROG_TYPE_SK_REUSEPORT:
 	case BPF_PROG_TYPE_FLOW_DISSECTOR:
-		return false;
 	case BPF_PROG_TYPE_UNSPEC:
-	case BPF_PROG_TYPE_KPROBE:
 	case BPF_PROG_TYPE_TRACEPOINT:
-	case BPF_PROG_TYPE_PERF_EVENT:
 	case BPF_PROG_TYPE_RAW_TRACEPOINT:
+	case BPF_PROG_TYPE_PERF_EVENT:
+		return false;
+	case BPF_PROG_TYPE_KPROBE:
 	default:
 		return true;
 	}
-- 
2.15.1

^ permalink raw reply related

* Re: [PATCH net-next,v3 09/12] flow_dissector: add basic ethtool_rx_flow_spec to flow_rule structure translator
From: Jiri Pirko @ 2018-11-22  6:19 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Pablo Neira Ayuso, netdev, davem, thomas.lendacky, ariel.elior,
	michael.chan, santosh, madalin.bucur, yisen.zhuang, salil.mehta,
	jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
	peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
	alexandre.torgue, joabreu, linux-net-drivers, ganeshgr, ogerlitz,
	Manish.Chopra
In-Reply-To: <191049db-be77-811b-1c6d-59c5c9a2d251@gmail.com>

Thu, Nov 22, 2018 at 05:57:31AM CET, f.fainelli@gmail.com wrote:
>
>
>On 11/20/2018 6:51 PM, Pablo Neira Ayuso wrote:
>> This patch adds a function to translate the ethtool_rx_flow_spec
>> structure to the flow_rule representation.
>> 
>> This allows us to reuse code from the driver side given that both flower
>> and ethtool_rx_flow interfaces use the same representation.
>> 
>> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
>> ---
>> v3: Suggested by Jiri Pirko:
>>         - Add struct ethtool_rx_flow_rule, keep placeholder to private
>>           dissector information.
>>     Reported by Manish Chopra:
>> 	- Fix incorrect dissector user_keys flags.
>> 
>>  include/linux/ethtool.h |  10 +++
>>  net/core/ethtool.c      | 189 ++++++++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 199 insertions(+)
>> 
>> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
>> index afd9596ce636..99849e0858b2 100644
>> --- a/include/linux/ethtool.h
>> +++ b/include/linux/ethtool.h
>> @@ -400,4 +400,14 @@ struct ethtool_ops {
>>  	void	(*get_ethtool_phy_stats)(struct net_device *,
>>  					 struct ethtool_stats *, u64 *);
>>  };
>> +
>> +struct ethtool_rx_flow_rule {
>> +	struct flow_rule	*rule;
>> +	unsigned long		priv[0];
>> +};
>> +
>> +struct ethtool_rx_flow_rule *
>> +ethtool_rx_flow_rule_alloc(const struct ethtool_rx_flow_spec *fs);
>> +void ethtool_rx_flow_rule_free(struct ethtool_rx_flow_rule *rule);
>> +
>>  #endif /* _LINUX_ETHTOOL_H */
>> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
>> index d05402868575..e679d6478371 100644
>> --- a/net/core/ethtool.c
>> +++ b/net/core/ethtool.c
>> @@ -28,6 +28,7 @@
>>  #include <linux/sched/signal.h>
>>  #include <linux/net.h>
>>  #include <net/xdp_sock.h>
>> +#include <net/flow_offload.h>
>>  
>>  /*
>>   * Some useful ethtool_ops methods that're device independent.
>> @@ -2808,3 +2809,191 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
>>  
>>  	return rc;
>>  }
>> +
>> +struct ethtool_rx_flow_key {
>> +	struct flow_dissector_key_basic			basic;
>> +	union {
>> +		struct flow_dissector_key_ipv4_addrs	ipv4;
>> +		struct flow_dissector_key_ipv6_addrs	ipv6;
>> +	};
>> +	struct flow_dissector_key_ports			tp;
>> +	struct flow_dissector_key_ip			ip;
>> +} __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */
>> +
>> +struct ethtool_rx_flow_match {
>> +	struct flow_dissector		dissector;
>> +	struct ethtool_rx_flow_key	key;
>> +	struct ethtool_rx_flow_key	mask;
>> +};
>> +
>> +struct ethtool_rx_flow_rule *
>> +ethtool_rx_flow_rule_alloc(const struct ethtool_rx_flow_spec *fs)
>
>This is more than alloc, it's allocate and map, no reason to split the
>two operations AFAICT, but the name could be improved, how about
>alloc_from()?

Or ethtool_rx_flow_rule_create() and ethtool_rx_flow_rule_destroy()


>
>> +{
>> +	static struct in6_addr zero_addr = {};
>> +	struct ethtool_rx_flow_match *match;
>> +	struct ethtool_rx_flow_rule *flow;
>> +	struct flow_action_entry *act;
>> +
>> +	flow = kzalloc(sizeof(struct ethtool_rx_flow_rule) +
>> +		       sizeof(struct ethtool_rx_flow_match), GFP_KERNEL);
>> +	if (!flow)
>> +		return NULL;
>> +
>> +	/* ethtool_rx supports only one single action per rule. */
>> +	flow->rule = flow_rule_alloc(1);
>> +	if (!flow->rule) {
>> +		kfree(flow);
>> +		return NULL;
>> +	}
>> +
>> +	match = (struct ethtool_rx_flow_match *)flow->priv;
>> +	flow->rule->match.dissector	= &match->dissector;
>> +	flow->rule->match.mask		= &match->mask;
>> +	flow->rule->match.key		= &match->key;
>> +
>> +	match->mask.basic.n_proto = 0xffff;
>> +
>> +	switch (fs->flow_type & ~FLOW_EXT) {
>> +	case TCP_V4_FLOW:
>> +	case UDP_V4_FLOW: {
>> +		const struct ethtool_tcpip4_spec *v4_spec, *v4_m_spec;
>> +
>> +		match->key.basic.n_proto = htons(ETH_P_IP);
>> +
>> +		v4_spec = &fs->h_u.tcp_ip4_spec;
>> +		v4_m_spec = &fs->m_u.tcp_ip4_spec;
>> +
>> +		if (v4_m_spec->ip4src) {
>> +			match->key.ipv4.src = v4_spec->ip4src;
>> +			match->mask.ipv4.src = v4_m_spec->ip4src;
>> +		}
>> +		if (v4_m_spec->ip4dst) {
>> +			match->key.ipv4.dst = v4_spec->ip4dst;
>> +			match->mask.ipv4.dst = v4_m_spec->ip4dst;
>> +		}
>
>I got confused a while ago between the ethtool ntuple and nfc semantics,
>and I can't remember if the following is true:
>
>- bits set to 1 indicate a match and bit set to 0 indicate a don't care
>for nfc
>- bits set to 0 indicate a match and bit set to 1 indicate a don't care
>for ntuple
>
>Depending on the answer that could mean that this check on a zero
>address may have to change.
>
>> +		if (v4_m_spec->ip4src ||
>> +		    v4_m_spec->ip4dst) {
>> +			match->dissector.used_keys |=
>> +				(1 << FLOW_DISSECTOR_KEY_IPV4_ADDRS);
>
>Can you use BIT() here (and likewise for every one below).
>
>[snip]
>> +
>> +	return flow;
>
>What about the extended fields and non-IP protocols?
>-- 
>Florian

^ permalink raw reply

* Re: [PATCH net-next,v3 09/12] flow_dissector: add basic ethtool_rx_flow_spec to flow_rule structure translator
From: Jiri Pirko @ 2018-11-22  6:21 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Pablo Neira Ayuso, netdev, davem, thomas.lendacky, ariel.elior,
	michael.chan, santosh, madalin.bucur, yisen.zhuang, salil.mehta,
	jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
	peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
	alexandre.torgue, joabreu, linux-net-drivers, ganeshgr, ogerlitz,
	Manish.Chopra
In-Reply-To: <ab835c1a-ef6c-82a4-b82e-f4341830c975@gmail.com>

Thu, Nov 22, 2018 at 05:59:27AM CET, f.fainelli@gmail.com wrote:
>
>
>On 11/20/2018 6:51 PM, Pablo Neira Ayuso wrote:
>> This patch adds a function to translate the ethtool_rx_flow_spec
>> structure to the flow_rule representation.
>> 
>> This allows us to reuse code from the driver side given that both flower
>> and ethtool_rx_flow interfaces use the same representation.
>> 
>> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
>> ---
>> v3: Suggested by Jiri Pirko:
>>         - Add struct ethtool_rx_flow_rule, keep placeholder to private
>>           dissector information.
>>     Reported by Manish Chopra:
>> 	- Fix incorrect dissector user_keys flags.
>> 
>>  include/linux/ethtool.h |  10 +++
>>  net/core/ethtool.c      | 189 ++++++++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 199 insertions(+)
>> 
>> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
>> index afd9596ce636..99849e0858b2 100644
>> --- a/include/linux/ethtool.h
>> +++ b/include/linux/ethtool.h
>> @@ -400,4 +400,14 @@ struct ethtool_ops {
>>  	void	(*get_ethtool_phy_stats)(struct net_device *,
>>  					 struct ethtool_stats *, u64 *);
>>  };
>> +
>> +struct ethtool_rx_flow_rule {
>> +	struct flow_rule	*rule;
>> +	unsigned long		priv[0];
>
>This forces you to cast to/from that member, any reason this is just not
>a void *priv here?

The reason is single alloc call for rule and its priv. Quite usual along
the code.


>-- 
>Florian

^ permalink raw reply

* [PATCH net 1/2] virtio-net: disable guest csum during XDP set
From: Jason Wang @ 2018-11-22  6:36 UTC (permalink / raw)
  To: mst, jasowang, davem, virtualization, netdev, linux-kernel
  Cc: Jesper Dangaard Brouer, Pavel Popa, David Ahern

We don't disable VIRTIO_NET_F_GUEST_CSUM if XDP was set. This means we
can receive partial csumed packets with metadata kept in the
vnet_hdr. This may have several side effects:

- It could be overridden by header adjustment, thus is might be not
  correct after XDP processing.
- There's no way to pass such metadata information through
  XDP_REDIRECT to another driver.
- XDP does not support checksum offload right now.

So simply disable guest csum if possible in this the case of XDP.

Fixes: 3f93522ffab2d ("virtio-net: switch off offloads on demand if possible on XDP set")
Reported-by: Jesper Dangaard Brouer <brouer@redhat.com>
Cc: Jesper Dangaard Brouer <brouer@redhat.com>
Cc: Pavel Popa <pashinho1990@gmail.com>
Cc: David Ahern <dsahern@gmail.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 drivers/net/virtio_net.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 3e2c041d76ac..9b5ace538824 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -70,7 +70,8 @@ static const unsigned long guest_offloads[] = {
 	VIRTIO_NET_F_GUEST_TSO4,
 	VIRTIO_NET_F_GUEST_TSO6,
 	VIRTIO_NET_F_GUEST_ECN,
-	VIRTIO_NET_F_GUEST_UFO
+	VIRTIO_NET_F_GUEST_UFO,
+	VIRTIO_NET_F_GUEST_CSUM
 };
 
 struct virtnet_stat_desc {
@@ -2334,9 +2335,6 @@ static int virtnet_clear_guest_offloads(struct virtnet_info *vi)
 	if (!vi->guest_offloads)
 		return 0;
 
-	if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_CSUM))
-		offloads = 1ULL << VIRTIO_NET_F_GUEST_CSUM;
-
 	return virtnet_set_guest_offloads(vi, offloads);
 }
 
@@ -2346,8 +2344,6 @@ static int virtnet_restore_guest_offloads(struct virtnet_info *vi)
 
 	if (!vi->guest_offloads)
 		return 0;
-	if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_CSUM))
-		offloads |= 1ULL << VIRTIO_NET_F_GUEST_CSUM;
 
 	return virtnet_set_guest_offloads(vi, offloads);
 }
-- 
2.17.1

^ permalink raw reply related

* Re: [BUG] xfrm: unable to handle kernel NULL pointer dereference
From: Steffen Klassert @ 2018-11-22  6:44 UTC (permalink / raw)
  To: Lennert Buytenhek
  Cc: herbert, Jean-Philippe Menil, davem, netdev, kuznet, yoshfuji
In-Reply-To: <20181116191246.GN8742@gauss3.secunet.de>

On Fri, Nov 16, 2018 at 08:12:46PM +0100, Steffen Klassert wrote:
> On Fri, Nov 16, 2018 at 08:48:00PM +0200, Lennert Buytenhek wrote:
> > On Sat, Nov 10, 2018 at 08:34:34PM +0100, Jean-Philippe Menil wrote:
> > 
> > > we're seeing unexpected crashes from kernel 4.15 to 4.18.17, using
> > > IPsec VTI interfaces, on several vpn hosts, since upgrade from 4.4.
> > 
> > I looked into this with Jean-Philippe, and it appears to be crashing
> > on a NULL pointer dereference in the inlined xfrm_policy_check() call
> > in vti_rcv_cb(), and specifically on the skb_dst(skb) dereference in
> > __xfrm_policy_check2():
> > 
> > 	return  (!net->xfrm.policy_count[dir] && !skb->sp) ||
> > 		(skb_dst(skb)->flags & DST_NOPOLICY) ||		<=====
> > 		__xfrm_policy_check(sk, ndir, skb, family);
> > 
> > Commit 9e1437937807 ("xfrm: Fix NULL pointer dereference when
> > skb_dst_force clears the dst_entry.") fixes a very similar problem on
> > the output and forward paths, but our issue seems to be triggering on
> > the input path.
> 
> Yes, this is the same problem. skb_dst_force() does not
> really force a refcount anymore, it might clear the dst
> pointer instead (maybe this function should be renamed).

I plan to apply this patch to the ipsec tree:

[PATCH RFC] xfrm: Fix NULL pointer dereference in xfrm_input when skb_dst_force clears the dst_entry.

Since commit 222d7dbd258d ("net: prevent dst uses after free")
skb_dst_force() might clear the dst_entry attached to the skb.
The xfrm code don't expect this to happen, so we crash with
a NULL pointer dereference in this case.

Fix it by checking skb_dst(skb) for NULL after skb_dst_force()
and drop the packet in cast the dst_entry was cleared. We also
move the skb_dst_force() to a codepath that is not used when
the transformation was offloaded, because in this case we
don't have a  dst_entry attached to the skb.

The output and forwarding path was already fixed by
commit 9e1437937807 ("xfrm: Fix NULL pointer dereference when
skb_dst_force clears the dst_entry.")

Fixes: 222d7dbd258d ("net: prevent dst uses after free")
Reported-by: Jean-Philippe Menil <jpmenil@gmail.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/xfrm/xfrm_input.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 684c0bc01e2c..d5635908587f 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -346,6 +346,12 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 
 		skb->sp->xvec[skb->sp->len++] = x;
 
+		skb_dst_force(skb);
+		if (!skb_dst(skb)) {
+			XFRM_INC_STATS(net, LINUX_MIB_XFRMINERROR);
+			goto drop;
+		}
+
 lock:
 		spin_lock(&x->lock);
 
@@ -385,7 +391,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 		XFRM_SKB_CB(skb)->seq.input.low = seq;
 		XFRM_SKB_CB(skb)->seq.input.hi = seq_hi;
 
-		skb_dst_force(skb);
 		dev_hold(skb->dev);
 
 		if (crypto_done)
-- 
2.17.1

^ permalink raw reply related

* Re: [PATCH net-next] ptp: Fix pass zero to ERR_PTR() in ptp_clock_register
From: kbuild test robot @ 2018-11-22 17:30 UTC (permalink / raw)
  To: YueHaibing
  Cc: kbuild-all, davem, richardcochran, dmitry.torokhov, linux-kernel,
	netdev, YueHaibing
In-Reply-To: <20181122133202.21908-1-yuehaibing@huawei.com>

[-- Attachment #1: Type: text/plain, Size: 7331 bytes --]

Hi YueHaibing,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on net-next/master]

url:    https://github.com/0day-ci/linux/commits/YueHaibing/ptp-Fix-pass-zero-to-ERR_PTR-in-ptp_clock_register/20181123-010251
config: x86_64-randconfig-x017-201846 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

   drivers/ptp/ptp_clock.c: In function 'ptp_clock_register':
>> drivers/ptp/ptp_clock.c:269:18: warning: passing argument 1 of 'PTR_ERR' makes pointer from integer without a cast [-Wint-conversion]
       err = PTR_ERR(-EINVAL);
                     ^
   In file included from arch/x86/include/asm/processor.h:32:0,
                    from arch/x86/include/asm/cpufeature.h:8,
                    from arch/x86/include/asm/thread_info.h:53,
                    from include/linux/thread_info.h:38,
                    from arch/x86/include/asm/preempt.h:7,
                    from include/linux/preempt.h:81,
                    from include/linux/radix-tree.h:27,
                    from include/linux/idr.h:15,
                    from drivers/ptp/ptp_clock.c:20:
   include/linux/err.h:29:33: note: expected 'const void *' but argument is of type 'int'
    static inline long __must_check PTR_ERR(__force const void *ptr)
                                    ^~~~~~~
   Cyclomatic Complexity 5 include/linux/compiler.h:__write_once_size
   Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:fls64
   Cyclomatic Complexity 1 include/linux/log2.h:__ilog2_u64
   Cyclomatic Complexity 1 include/linux/list.h:INIT_LIST_HEAD
   Cyclomatic Complexity 1 include/linux/math64.h:div_u64_rem
   Cyclomatic Complexity 1 include/asm-generic/getorder.h:__get_order
   Cyclomatic Complexity 3 include/linux/string.h:memset
   Cyclomatic Complexity 1 include/linux/err.h:ERR_PTR
   Cyclomatic Complexity 1 include/linux/err.h:PTR_ERR
   Cyclomatic Complexity 1 include/linux/spinlock.h:spinlock_check
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_unlock_irqrestore
   Cyclomatic Complexity 1 include/linux/ktime.h:ktime_to_ns
   Cyclomatic Complexity 1 include/linux/slab.h:kmalloc_type
   Cyclomatic Complexity 28 include/linux/slab.h:kmalloc_index
   Cyclomatic Complexity 68 include/linux/slab.h:kmalloc_large
   Cyclomatic Complexity 4 include/linux/slab.h:kmalloc
   Cyclomatic Complexity 1 include/linux/slab.h:kzalloc
   Cyclomatic Complexity 2 drivers/ptp/ptp_private.h:queue_cnt
   Cyclomatic Complexity 1 drivers/ptp/ptp_clock.c:queue_free
   Cyclomatic Complexity 2 drivers/ptp/ptp_clock.c:enqueue_external_timestamp
   Cyclomatic Complexity 1 drivers/ptp/ptp_clock.c:scaled_ppm_to_ppb
   Cyclomatic Complexity 1 drivers/ptp/ptp_clock.c:ptp_clock_getres
   Cyclomatic Complexity 1 drivers/ptp/ptp_clock.c:ptp_clock_settime
   Cyclomatic Complexity 2 drivers/ptp/ptp_clock.c:ptp_clock_gettime
   Cyclomatic Complexity 1 drivers/ptp/ptp_clock.c:delete_ptp_clock
   Cyclomatic Complexity 2 drivers/ptp/ptp_clock.c:ptp_aux_kworker
   Cyclomatic Complexity 2 include/linux/ktime.h:ktime_set
   Cyclomatic Complexity 1 include/linux/ktime.h:timespec64_to_ktime
   Cyclomatic Complexity 9 drivers/ptp/ptp_clock.c:ptp_clock_adjtime
   Cyclomatic Complexity 1 include/linux/err.h:IS_ERR
   Cyclomatic Complexity 1 include/linux/pps_kernel.h:pps_get_ts
   Cyclomatic Complexity 1 drivers/ptp/ptp_clock.c:ptp_exit
   Cyclomatic Complexity 3 drivers/ptp/ptp_clock.c:ptp_init
   Cyclomatic Complexity 13 drivers/ptp/ptp_clock.c:ptp_clock_register
   Cyclomatic Complexity 3 drivers/ptp/ptp_clock.c:ptp_clock_unregister
   Cyclomatic Complexity 4 drivers/ptp/ptp_clock.c:ptp_clock_event
   Cyclomatic Complexity 1 drivers/ptp/ptp_clock.c:ptp_clock_index
   Cyclomatic Complexity 5 drivers/ptp/ptp_clock.c:ptp_find_pin
   Cyclomatic Complexity 1 drivers/ptp/ptp_clock.c:ptp_schedule_worker

vim +/PTR_ERR +269 drivers/ptp/ptp_clock.c

   205	
   206	struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
   207					     struct device *parent)
   208	{
   209		struct ptp_clock *ptp;
   210		int err = 0, index, major = MAJOR(ptp_devt);
   211	
   212		if (info->n_alarm > PTP_MAX_ALARMS)
   213			return ERR_PTR(-EINVAL);
   214	
   215		/* Initialize a clock structure. */
   216		err = -ENOMEM;
   217		ptp = kzalloc(sizeof(struct ptp_clock), GFP_KERNEL);
   218		if (ptp == NULL)
   219			goto no_memory;
   220	
   221		index = ida_simple_get(&ptp_clocks_map, 0, MINORMASK + 1, GFP_KERNEL);
   222		if (index < 0) {
   223			err = index;
   224			goto no_slot;
   225		}
   226	
   227		ptp->clock.ops = ptp_clock_ops;
   228		ptp->clock.release = delete_ptp_clock;
   229		ptp->info = info;
   230		ptp->devid = MKDEV(major, index);
   231		ptp->index = index;
   232		spin_lock_init(&ptp->tsevq.lock);
   233		mutex_init(&ptp->tsevq_mux);
   234		mutex_init(&ptp->pincfg_mux);
   235		init_waitqueue_head(&ptp->tsev_wq);
   236	
   237		if (ptp->info->do_aux_work) {
   238			kthread_init_delayed_work(&ptp->aux_work, ptp_aux_kworker);
   239			ptp->kworker = kthread_create_worker(0, "ptp%d", ptp->index);
   240			if (IS_ERR(ptp->kworker)) {
   241				err = PTR_ERR(ptp->kworker);
   242				pr_err("failed to create ptp aux_worker %d\n", err);
   243				goto kworker_err;
   244			}
   245		}
   246	
   247		err = ptp_populate_pin_groups(ptp);
   248		if (err)
   249			goto no_pin_groups;
   250	
   251		/* Create a new device in our class. */
   252		ptp->dev = device_create_with_groups(ptp_class, parent, ptp->devid,
   253						     ptp, ptp->pin_attr_groups,
   254						     "ptp%d", ptp->index);
   255		if (IS_ERR(ptp->dev)) {
   256			err = PTR_ERR(ptp->dev);
   257			goto no_device;
   258		}
   259	
   260		/* Register a new PPS source. */
   261		if (info->pps) {
   262			struct pps_source_info pps;
   263			memset(&pps, 0, sizeof(pps));
   264			snprintf(pps.name, PPS_MAX_NAME_LEN, "ptp%d", index);
   265			pps.mode = PTP_PPS_MODE;
   266			pps.owner = info->owner;
   267			ptp->pps_source = pps_register_source(&pps, PTP_PPS_DEFAULTS);
   268			if (!ptp->pps_source) {
 > 269				err = PTR_ERR(-EINVAL);
   270				pr_err("failed to register pps source\n");
   271				goto no_pps;
   272			}
   273		}
   274	
   275		/* Create a posix clock. */
   276		err = posix_clock_register(&ptp->clock, ptp->devid);
   277		if (err) {
   278			pr_err("failed to create posix clock\n");
   279			goto no_clock;
   280		}
   281	
   282		return ptp;
   283	
   284	no_clock:
   285		if (ptp->pps_source)
   286			pps_unregister_source(ptp->pps_source);
   287	no_pps:
   288		device_destroy(ptp_class, ptp->devid);
   289	no_device:
   290		ptp_cleanup_pin_groups(ptp);
   291	no_pin_groups:
   292		if (ptp->kworker)
   293			kthread_destroy_worker(ptp->kworker);
   294	kworker_err:
   295		mutex_destroy(&ptp->tsevq_mux);
   296		mutex_destroy(&ptp->pincfg_mux);
   297		ida_simple_remove(&ptp_clocks_map, index);
   298	no_slot:
   299		kfree(ptp);
   300	no_memory:
   301		return ERR_PTR(err);
   302	}
   303	EXPORT_SYMBOL(ptp_clock_register);
   304	

---
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: 28309 bytes --]

^ permalink raw reply

* invalid opcode in ip_do_fragment
From: syzbot @ 2018-11-22 18:03 UTC (permalink / raw)
  To: davem, kuznet, linux-kernel, netdev, syzkaller-bugs, yoshfuji

Hello,

syzbot found the following crash on:

HEAD commit:    92b419289cee Merge tag 'riscv-for-linus-4.20-rc4' of git:/..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=12243093400000
kernel config:  https://syzkaller.appspot.com/x/.config?x=73e2bc0cb6463446
dashboard link: https://syzkaller.appspot.com/bug?extid=865704dc4f7ff5d1a04b
compiler:       gcc (GCC) 8.0.1 20180413 (experimental)

Unfortunately, I don't have any reproducer for this crash yet.

IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+865704dc4f7ff5d1a04b@syzkaller.appspotmail.com

invalid opcode: 0000 [#1] PREEMPT SMP KASAN
CPU: 0 PID: 21078 Comm: syz-executor1 Not tainted 4.20.0-rc3+ #344
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS  
Google 01/01/2011
RIP: 0010:ip_do_fragment+0x2447/0x2ad0 net/ipv4/ip_output.c:776
Code: ff 48 89 cf e8 2a 36 23 fb e9 dc ea ff ff 48 89 df e8 5d 36 23 fb e9  
02 e7 ff ff e8 b3 36 23 fb e9 97 e6 ff ff e8 29 e7 df fa <0f> 0b 4c 89 f7  
e8 ff 35 23 fb e9 2f e6 ff ff 4c 89 e7 e8 f2 35 23
RSP: 0018:ffff88818232e7b8 EFLAGS: 00010246
RAX: 0000000000040000 RBX: ffff8881d3af0800 RCX: ffffc9000c0db000
RDX: 0000000000040000 RSI: ffffffff869fa3c7 RDI: 0000000000000005
RBP: ffff88818232e990 R08: ffff88816ba06580 R09: ffffed10342f86ca
R10: ffffed10342f86cc R11: ffff8881a17c3663 R12: ffff8881d3af08c4
R13: 00000000fffffff2 R14: ffff8881d3af08d0 R15: dffffc0000000000
FS:  00007fa003fcd700(0000) GS:ffff8881dae00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00000000004ccd10 CR3: 0000000199f89000 CR4: 00000000001426f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
  ip_fragment.constprop.50+0x179/0x240 net/ipv4/ip_output.c:549
  ip_finish_output+0x6b4/0xfa0 net/ipv4/ip_output.c:315
  NF_HOOK_COND include/linux/netfilter.h:278 [inline]
  ip_output+0x21d/0x8d0 net/ipv4/ip_output.c:405
  dst_output include/net/dst.h:444 [inline]
  ip_local_out+0xc5/0x1b0 net/ipv4/ip_output.c:124
  iptunnel_xmit+0x63b/0x9c0 net/ipv4/ip_tunnel_core.c:91
  ip_tunnel_xmit+0x15b8/0x3c04 net/ipv4/ip_tunnel.c:787
  __gre_xmit+0x5e1/0x980 net/ipv4/ip_gre.c:451
  ipgre_xmit+0x3e7/0xba0 net/ipv4/ip_gre.c:705
  __netdev_start_xmit include/linux/netdevice.h:4356 [inline]
  netdev_start_xmit include/linux/netdevice.h:4365 [inline]
  xmit_one net/core/dev.c:3252 [inline]
  dev_hard_start_xmit+0x295/0xc80 net/core/dev.c:3268
  __dev_queue_xmit+0x2f71/0x3ad0 net/core/dev.c:3838
  dev_queue_xmit+0x17/0x20 net/core/dev.c:3871
  __bpf_tx_skb net/core/filter.c:2017 [inline]
  __bpf_redirect_common net/core/filter.c:2055 [inline]
  __bpf_redirect+0x5cf/0xb20 net/core/filter.c:2062
  ____bpf_clone_redirect net/core/filter.c:2095 [inline]
  bpf_clone_redirect+0x2f6/0x490 net/core/filter.c:2067
  bpf_prog_bebbfe2050753572+0x7dd/0x1000
Modules linked in:
---[ end trace 0d51d2ed64b21356 ]---
RIP: 0010:ip_do_fragment+0x2447/0x2ad0 net/ipv4/ip_output.c:776
Code: ff 48 89 cf e8 2a 36 23 fb e9 dc ea ff ff 48 89 df e8 5d 36 23 fb e9  
02 e7 ff ff e8 b3 36 23 fb e9 97 e6 ff ff e8 29 e7 df fa <0f> 0b 4c 89 f7  
e8 ff 35 23 fb e9 2f e6 ff ff 4c 89 e7 e8 f2 35 23
RSP: 0018:ffff88818232e7b8 EFLAGS: 00010246
RAX: 0000000000040000 RBX: ffff8881d3af0800 RCX: ffffc9000c0db000
RDX: 0000000000040000 RSI: ffffffff869fa3c7 RDI: 0000000000000005
RBP: ffff88818232e990 R08: ffff88816ba06580 R09: ffffed10342f86ca
R10: ffffed10342f86cc R11: ffff8881a17c3663 R12: ffff8881d3af08c4
R13: 00000000fffffff2 R14: ffff8881d3af08d0 R15: dffffc0000000000
FS:  00007fa003fcd700(0000) GS:ffff8881dae00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00000000004ccd10 CR3: 0000000199f89000 CR4: 00000000001426f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400


---
This bug is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.

syzbot will keep track of this bug report. See:
https://goo.gl/tpsmEJ#bug-status-tracking for how to communicate with  
syzbot.

^ permalink raw reply

* Re: [PATCH net-next v2 1/4] enetc: Introduce basic PF and VF ENETC ethernet drivers
From: Andrew Lunn @ 2018-11-22 18:05 UTC (permalink / raw)
  To: Claudiu Manoil
  Cc: David Miller, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, Alexandru Marginean,
	Catalin Horghidan
In-Reply-To: <VI1PR04MB48803D4A3D8D331046CFC63196DB0@VI1PR04MB4880.eurprd04.prod.outlook.com>

On Thu, Nov 22, 2018 at 01:06:01PM +0000, Claudiu Manoil wrote:
> >-----Original Message-----
> >From: David Miller <davem@davemloft.net>
> >Sent: Thursday, November 22, 2018 2:21 AM
> >To: Claudiu Manoil <claudiu.manoil@nxp.com>
> >Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org; Alexandru
> >Marginean <alexandru.marginean@nxp.com>; Catalin Horghidan
> ><catalin.horghidan@nxp.com>
> >Subject: Re: [PATCH net-next v2 1/4] enetc: Introduce basic PF and VF ENETC
> >ethernet drivers
> >
> >From: Claudiu Manoil <claudiu.manoil@nxp.com>
> >Date: Tue, 20 Nov 2018 20:15:31 +0200
> >
> >> diff --git a/drivers/net/ethernet/freescale/Makefile
> >b/drivers/net/ethernet/freescale/Makefile
> >> index 3b4ff08..20e5c2f9 100644
> >> --- a/drivers/net/ethernet/freescale/Makefile
> >> +++ b/drivers/net/ethernet/freescale/Makefile
> >> @@ -23,3 +23,4 @@ obj-$(CONFIG_FSL_FMAN) += fman/
> >>  obj-$(CONFIG_FSL_DPAA_ETH) += dpaa/
> >>
> >>  obj-$(CONFIG_FSL_DPAA2_ETH) += dpaa2/
> >> +obj-$(CONFIG_NET_VENDOR_FREESCALE) += enetc/
> >
> >The driver enable Kconfig option should guard traversing into the
> >driver subdirectory, not the vendor enable Kconfig knob.
> 
> The enetc/ dir contains 2 drivers, that share a lot of common code.
> Would you agree if I change the vendor enable with the two configs
> (one for each driver) as below?
> 
> -obj-$(CONFIG_NET_VENDOR_FREESCALE) += enetc/
> +obj-$(CONFIG_FSL_ENETC) += enetc/
> +obj-$(CONFIG_FSL_ENETC_VF) += enetc/

CONFIG_NET_VENDOR_FREESCALE should hide/show all Freescale drivers.

Once you show all Freescale drivers, there should be an option to
enable each individual driver.

Does the ENETC_VF driver depend on the ENETC driver? If so, when
CONFIG_FSL_ENETC is enabled, the CONFIG_FSL_ENETC_VF should be
unhidden.

	Andrew

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox