Netdev List
 help / color / mirror / Atom feed
* WARNING: refcount bug in llc_sap_find
From: syzbot @ 2018-08-07 14:59 UTC (permalink / raw)
  To: davem, linux-kernel, netdev, syzkaller-bugs

Hello,

syzbot found the following crash on:

HEAD commit:    0585df468e8f Merge tag 'media/v4.18-3' of git://git.kernel..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=15927272400000
kernel config:  https://syzkaller.appspot.com/x/.config?x=2dc0cd7c2eefb46f
dashboard link: https://syzkaller.appspot.com/bug?extid=278893f3f7803871f7ce
compiler:       gcc (GCC) 8.0.1 20180413 (experimental)
syzkaller repro:https://syzkaller.appspot.com/x/repro.syz?x=1064ef78400000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=17d0fa8c400000

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

------------[ cut here ]------------
refcount_t: increment on 0; use-after-free.
WARNING: CPU: 0 PID: 25217 at lib/refcount.c:153 refcount_inc+0x5d/0x70  
lib/refcount.c:153
Kernel panic - not syncing: panic_on_warn set ...

CPU: 0 PID: 25217 Comm: syz-executor271 Not tainted 4.18.0-rc7+ #175
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+0x1c9/0x2b4 lib/dump_stack.c:113
  panic+0x238/0x4e7 kernel/panic.c:184
  __warn.cold.8+0x163/0x1ba kernel/panic.c:536
  report_bug+0x252/0x2d0 lib/bug.c:186
  fixup_bug arch/x86/kernel/traps.c:178 [inline]
  do_error_trap+0x1fc/0x4d0 arch/x86/kernel/traps.c:296
  do_invalid_op+0x1b/0x20 arch/x86/kernel/traps.c:316
  invalid_op+0x14/0x20 arch/x86/entry/entry_64.S:992
RIP: 0010:refcount_inc+0x5d/0x70 lib/refcount.c:153
Code: 1d 9c ef 25 05 31 ff 89 de e8 6f b0 1c fe 84 db 75 df e8 96 af 1c fe  
48 c7 c7 40 4b 3a 87 c6 05 7c ef 25 05 01 e8 93 c8 e7 fd <0f> 0b eb c3 0f  
1f 44 00 00 66 2e 0f 1f 84 00 00 00 00 00 55 48 89
RSP: 0018:ffff8801d6cd7af8 EFLAGS: 00010286
RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
RDX: 0000000000000000 RSI: ffffffff81632481 RDI: ffff8801d6cd77d0
RBP: ffff8801d6cd7b00 R08: ffff8801bfbf65c0 R09: 0000000000000002
R10: ffff8801bfbf65c0 R11: 0000000000000000 R12: 00000000000000ff
R13: dffffc0000000000 R14: 00000000000000ff R15: ffff8801d6cd7d17
  llc_sap_hold include/net/llc.h:116 [inline]
  llc_sap_find+0x1ec/0x2a0 net/llc/llc_core.c:77
  llc_ui_bind+0x6c7/0xf10 net/llc/af_llc.c:362
  __sys_bind+0x331/0x440 net/socket.c:1493
  __do_sys_bind net/socket.c:1504 [inline]
  __se_sys_bind net/socket.c:1502 [inline]
  __x64_sys_bind+0x73/0xb0 net/socket.c:1502
  do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290
  entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x445ca9
Code: e8 ac e7 ff ff 48 83 c4 18 c3 0f 1f 80 00 00 00 00 48 89 f8 48 89 f7  
48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff  
ff 0f 83 fb 0d fc ff c3 66 2e 0f 1f 84 00 00 00 00
RSP: 002b:00007ff435ebcdb8 EFLAGS: 00000246 ORIG_RAX: 0000000000000031
RAX: ffffffffffffffda RBX: 00000000006dac28 RCX: 0000000000445ca9
RDX: 0000000000000010 RSI: 00000000200000c0 RDI: 0000000000000003
RBP: 00000000006dac20 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 00000000006dac2c
R13: 00007ffe0636e23f R14: 00007ff435ebd9c0 R15: 00000000006dac20
Dumping ftrace buffer:
    (ftrace buffer empty)
Kernel Offset: disabled
Rebooting in 86400 seconds..


---
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.
syzbot can test patches for this bug, for details see:
https://goo.gl/tpsmEJ#testing-patches

^ permalink raw reply

* Re: [PATCH net-next] ceph: remove unnecessary non NULL check for request_key
From: Ilya Dryomov @ 2018-08-07 15:02 UTC (permalink / raw)
  To: yuehaibing
  Cc: David S. Miller, Yan, Zheng, Sage Weil, linux-kernel, netdev,
	Ceph Development
In-Reply-To: <20180807130234.5380-1-yuehaibing@huawei.com>

On Tue, Aug 7, 2018 at 3:03 PM YueHaibing <yuehaibing@huawei.com> wrote:
>
> request_key never return NULL,so no need do non-NULL check.
>
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
> ---
>  net/ceph/ceph_common.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
> index 584fdbe..9834edc 100644
> --- a/net/ceph/ceph_common.c
> +++ b/net/ceph/ceph_common.c
> @@ -304,7 +304,7 @@ static int get_secret(struct ceph_crypto_key *dst, const char *name) {
>         struct ceph_crypto_key *ckey;
>
>         ukey = request_key(&key_type_ceph, name, NULL);
> -       if (!ukey || IS_ERR(ukey)) {
> +       if (IS_ERR(ukey)) {
>                 /* request_key errors don't map nicely to mount(2)
>                    errors; don't even try, but still printk */
>                 key_err = PTR_ERR(ukey);

Applied.

Thanks,

                Ilya

^ permalink raw reply

* [PATCH net-next v3 1/3] qed: Add DCBX API - qed_dcbx_get_priority_tc()
From: Denis Bolotin @ 2018-08-07 12:48 UTC (permalink / raw)
  To: davem, netdev; +Cc: Denis Bolotin, Michal Kalderon, Ariel Elior
In-Reply-To: <20180807124810.17386-1-denis.bolotin@cavium.com>

The API receives a priority and looks for the TC it is mapped to in the
operational DCBX configuration. The API returns QED_DCBX_DEFAULT_TC (0)
when DCBX is disabled.

Signed-off-by: Michal Kalderon <michal.kalderon@cavium.com>
Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
Signed-off-by: Denis Bolotin <denis.bolotin@cavium.com>
---
 drivers/net/ethernet/qlogic/qed/qed_dcbx.c | 18 ++++++++++++++++++
 drivers/net/ethernet/qlogic/qed/qed_dcbx.h |  3 +++
 2 files changed, 21 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c
index d02e774..86307b9 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c
@@ -989,6 +989,24 @@ void qed_dcbx_set_pf_update_params(struct qed_dcbx_results *p_src,
 	qed_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_ETH);
 }
 
+u8 qed_dcbx_get_priority_tc(struct qed_hwfn *p_hwfn, u8 pri)
+{
+	struct qed_dcbx_get *dcbx_info = &p_hwfn->p_dcbx_info->get;
+
+	if (pri >= QED_MAX_PFC_PRIORITIES) {
+		DP_ERR(p_hwfn, "Invalid priority %d\n", pri);
+		return QED_DCBX_DEFAULT_TC;
+	}
+
+	if (!dcbx_info->operational.valid) {
+		DP_VERBOSE(p_hwfn, QED_MSG_DCB,
+			   "Dcbx parameters not available\n");
+		return QED_DCBX_DEFAULT_TC;
+	}
+
+	return dcbx_info->operational.params.ets_pri_tc_tbl[pri];
+}
+
 #ifdef CONFIG_DCB
 static int qed_dcbx_query_params(struct qed_hwfn *p_hwfn,
 				 struct qed_dcbx_get *p_get,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dcbx.h b/drivers/net/ethernet/qlogic/qed/qed_dcbx.h
index 5feb90e..a4d688c 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dcbx.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_dcbx.h
@@ -123,4 +123,7 @@ int qed_dcbx_config_params(struct qed_hwfn *,
 void qed_dcbx_set_pf_update_params(struct qed_dcbx_results *p_src,
 				   struct pf_update_ramrod_data *p_dest);
 
+#define QED_DCBX_DEFAULT_TC	0
+
+u8 qed_dcbx_get_priority_tc(struct qed_hwfn *p_hwfn, u8 pri);
 #endif
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net-next v3 2/3] qed: Add a flag which indicates if offload TC is set
From: Denis Bolotin @ 2018-08-07 12:48 UTC (permalink / raw)
  To: davem, netdev; +Cc: Denis Bolotin, Michal Kalderon, Ariel Elior
In-Reply-To: <20180807124810.17386-1-denis.bolotin@cavium.com>

Distinguish not set offload_tc from offload_tc 0 and add getters and
setters.

Signed-off-by: Michal Kalderon <michal.kalderon@cavium.com>
Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
Signed-off-by: Denis Bolotin <denis.bolotin@cavium.com>
---
 drivers/net/ethernet/qlogic/qed/qed.h      |  3 +++
 drivers/net/ethernet/qlogic/qed/qed_dcbx.c |  2 +-
 drivers/net/ethernet/qlogic/qed/qed_dev.c  | 32 +++++++++++++++++++++++++-----
 drivers/net/ethernet/qlogic/qed/qed_mcp.c  |  3 ++-
 4 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h
index 1dfaccd..f916f13 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -336,6 +336,7 @@ struct qed_hw_info {
 	 */
 	u8 num_active_tc;
 	u8				offload_tc;
+	bool				offload_tc_set;
 
 	u32				concrete_fid;
 	u16				opaque_fid;
@@ -921,4 +922,6 @@ void qed_get_protocol_stats(struct qed_dev *cdev,
 int qed_mfw_fill_tlv_data(struct qed_hwfn *hwfn,
 			  enum qed_mfw_tlv_type type,
 			  union qed_mfw_tlv_data *tlv_data);
+
+void qed_hw_info_set_offload_tc(struct qed_hw_info *p_info, u8 tc);
 #endif /* _QED_H */
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c
index 86307b9..6bb76e6 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c
@@ -208,7 +208,7 @@ static bool qed_dcbx_roce_v2_tlv(u32 app_info_bitmap, u16 proto_id, bool ieee)
 
 	/* QM reconf data */
 	if (p_info->personality == personality)
-		p_info->offload_tc = tc;
+		qed_hw_info_set_offload_tc(p_info, tc);
 }
 
 /* Update app protocol data and hw_info fields with the TLV info */
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index 6a0b46f..a8e7683 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -394,7 +394,25 @@ static void qed_init_qm_advance_vport(struct qed_hwfn *p_hwfn)
 /* defines for pq init */
 #define PQ_INIT_DEFAULT_WRR_GROUP       1
 #define PQ_INIT_DEFAULT_TC              0
-#define PQ_INIT_OFLD_TC                 (p_hwfn->hw_info.offload_tc)
+
+void qed_hw_info_set_offload_tc(struct qed_hw_info *p_info, u8 tc)
+{
+	p_info->offload_tc = tc;
+	p_info->offload_tc_set = true;
+}
+
+static bool qed_is_offload_tc_set(struct qed_hwfn *p_hwfn)
+{
+	return p_hwfn->hw_info.offload_tc_set;
+}
+
+static u32 qed_get_offload_tc(struct qed_hwfn *p_hwfn)
+{
+	if (qed_is_offload_tc_set(p_hwfn))
+		return p_hwfn->hw_info.offload_tc;
+
+	return PQ_INIT_DEFAULT_TC;
+}
 
 static void qed_init_qm_pq(struct qed_hwfn *p_hwfn,
 			   struct qed_qm_info *qm_info,
@@ -538,7 +556,8 @@ static void qed_init_qm_pure_ack_pq(struct qed_hwfn *p_hwfn)
 		return;
 
 	qed_init_qm_set_idx(p_hwfn, PQ_FLAGS_ACK, qm_info->num_pqs);
-	qed_init_qm_pq(p_hwfn, qm_info, PQ_INIT_OFLD_TC, PQ_INIT_SHARE_VPORT);
+	qed_init_qm_pq(p_hwfn, qm_info, qed_get_offload_tc(p_hwfn),
+		       PQ_INIT_SHARE_VPORT);
 }
 
 static void qed_init_qm_offload_pq(struct qed_hwfn *p_hwfn)
@@ -549,7 +568,8 @@ static void qed_init_qm_offload_pq(struct qed_hwfn *p_hwfn)
 		return;
 
 	qed_init_qm_set_idx(p_hwfn, PQ_FLAGS_OFLD, qm_info->num_pqs);
-	qed_init_qm_pq(p_hwfn, qm_info, PQ_INIT_OFLD_TC, PQ_INIT_SHARE_VPORT);
+	qed_init_qm_pq(p_hwfn, qm_info, qed_get_offload_tc(p_hwfn),
+		       PQ_INIT_SHARE_VPORT);
 }
 
 static void qed_init_qm_low_latency_pq(struct qed_hwfn *p_hwfn)
@@ -560,7 +580,8 @@ static void qed_init_qm_low_latency_pq(struct qed_hwfn *p_hwfn)
 		return;
 
 	qed_init_qm_set_idx(p_hwfn, PQ_FLAGS_LLT, qm_info->num_pqs);
-	qed_init_qm_pq(p_hwfn, qm_info, PQ_INIT_OFLD_TC, PQ_INIT_SHARE_VPORT);
+	qed_init_qm_pq(p_hwfn, qm_info, qed_get_offload_tc(p_hwfn),
+		       PQ_INIT_SHARE_VPORT);
 }
 
 static void qed_init_qm_mcos_pqs(struct qed_hwfn *p_hwfn)
@@ -601,7 +622,8 @@ static void qed_init_qm_rl_pqs(struct qed_hwfn *p_hwfn)
 
 	qed_init_qm_set_idx(p_hwfn, PQ_FLAGS_RLS, qm_info->num_pqs);
 	for (pf_rls_idx = 0; pf_rls_idx < num_pf_rls; pf_rls_idx++)
-		qed_init_qm_pq(p_hwfn, qm_info, PQ_INIT_OFLD_TC, PQ_INIT_PF_RL);
+		qed_init_qm_pq(p_hwfn, qm_info, qed_get_offload_tc(p_hwfn),
+			       PQ_INIT_PF_RL);
 }
 
 static void qed_init_qm_pq_params(struct qed_hwfn *p_hwfn)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index 8e4f60e..d89a0e2 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -1552,7 +1552,8 @@ void qed_mcp_read_ufp_config(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 
 	if (p_hwfn->ufp_info.mode == QED_UFP_MODE_VNIC_BW) {
 		p_hwfn->qm_info.ooo_tc = p_hwfn->ufp_info.tc;
-		p_hwfn->hw_info.offload_tc = p_hwfn->ufp_info.tc;
+		qed_hw_info_set_offload_tc(&p_hwfn->hw_info,
+					   p_hwfn->ufp_info.tc);
 
 		qed_qm_reconf(p_hwfn, p_ptt);
 	} else if (p_hwfn->ufp_info.mode == QED_UFP_MODE_ETS) {
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net-next v3 3/3] qed: Add Multi-TC RoCE support
From: Denis Bolotin @ 2018-08-07 12:48 UTC (permalink / raw)
  To: davem, netdev; +Cc: Denis Bolotin, Michal Kalderon, Ariel Elior
In-Reply-To: <20180807124810.17386-1-denis.bolotin@cavium.com>

RoCE qps use a pair of physical queues (pq) received from the Queue Manager
(QM) - an offload queue (OFLD) and a low latency queue (LLT). The QM block
creates a pq for each TC, and allows RoCE qps to ask for a pq with a
specific TC. As a result, qps with different VLAN priorities can be mapped
to different TCs, and employ features such as PFC and ETS.

Signed-off-by: Michal Kalderon <michal.kalderon@cavium.com>
Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
Signed-off-by: Denis Bolotin <denis.bolotin@cavium.com>
---
 drivers/net/ethernet/qlogic/qed/qed.h      | 10 +++-
 drivers/net/ethernet/qlogic/qed/qed_dev.c  | 89 +++++++++++++++++++++++++-----
 drivers/net/ethernet/qlogic/qed/qed_roce.c | 54 ++++++++++++------
 3 files changed, 121 insertions(+), 32 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h
index f916f13..a60e1c8 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -338,6 +338,9 @@ struct qed_hw_info {
 	u8				offload_tc;
 	bool				offload_tc_set;
 
+	bool				multi_tc_roce_en;
+#define IS_QED_MULTI_TC_ROCE(p_hwfn) (((p_hwfn)->hw_info.multi_tc_roce_en))
+
 	u32				concrete_fid;
 	u16				opaque_fid;
 	u16				ovlan;
@@ -400,8 +403,8 @@ struct qed_qm_info {
 	u16				start_pq;
 	u8				start_vport;
 	u16				 pure_lb_pq;
-	u16				offload_pq;
-	u16				low_latency_pq;
+	u16				first_ofld_pq;
+	u16				first_llt_pq;
 	u16				pure_ack_pq;
 	u16				ooo_pq;
 	u16				first_vf_pq;
@@ -882,11 +885,14 @@ void qed_set_fw_mac_addr(__le16 *fw_msb,
 #define PQ_FLAGS_OFLD   (BIT(5))
 #define PQ_FLAGS_VFS    (BIT(6))
 #define PQ_FLAGS_LLT    (BIT(7))
+#define PQ_FLAGS_MTC    (BIT(8))
 
 /* physical queue index for cm context intialization */
 u16 qed_get_cm_pq_idx(struct qed_hwfn *p_hwfn, u32 pq_flags);
 u16 qed_get_cm_pq_idx_mcos(struct qed_hwfn *p_hwfn, u8 tc);
 u16 qed_get_cm_pq_idx_vf(struct qed_hwfn *p_hwfn, u16 vf);
+u16 qed_get_cm_pq_idx_ofld_mtc(struct qed_hwfn *p_hwfn, u8 tc);
+u16 qed_get_cm_pq_idx_llt_mtc(struct qed_hwfn *p_hwfn, u8 tc);
 
 #define QED_LEADING_HWFN(dev)   (&dev->hwfns[0])
 
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index a8e7683..d1ae11a 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -215,6 +215,8 @@ static u32 qed_get_pq_flags(struct qed_hwfn *p_hwfn)
 		break;
 	case QED_PCI_ETH_ROCE:
 		flags |= PQ_FLAGS_MCOS | PQ_FLAGS_OFLD | PQ_FLAGS_LLT;
+		if (IS_QED_MULTI_TC_ROCE(p_hwfn))
+			flags |= PQ_FLAGS_MTC;
 		break;
 	case QED_PCI_ETH_IWARP:
 		flags |= PQ_FLAGS_MCOS | PQ_FLAGS_ACK | PQ_FLAGS_OOO |
@@ -241,6 +243,16 @@ static u16 qed_init_qm_get_num_vfs(struct qed_hwfn *p_hwfn)
 	       p_hwfn->cdev->p_iov_info->total_vfs : 0;
 }
 
+static u8 qed_init_qm_get_num_mtc_tcs(struct qed_hwfn *p_hwfn)
+{
+	u32 pq_flags = qed_get_pq_flags(p_hwfn);
+
+	if (!(PQ_FLAGS_MTC & pq_flags))
+		return 1;
+
+	return qed_init_qm_get_num_tcs(p_hwfn);
+}
+
 #define NUM_DEFAULT_RLS 1
 
 static u16 qed_init_qm_get_num_pf_rls(struct qed_hwfn *p_hwfn)
@@ -282,8 +294,11 @@ static u16 qed_init_qm_get_num_pqs(struct qed_hwfn *p_hwfn)
 	       (!!(PQ_FLAGS_MCOS & pq_flags)) *
 	       qed_init_qm_get_num_tcs(p_hwfn) +
 	       (!!(PQ_FLAGS_LB & pq_flags)) + (!!(PQ_FLAGS_OOO & pq_flags)) +
-	       (!!(PQ_FLAGS_ACK & pq_flags)) + (!!(PQ_FLAGS_OFLD & pq_flags)) +
-	       (!!(PQ_FLAGS_LLT & pq_flags)) +
+	       (!!(PQ_FLAGS_ACK & pq_flags)) +
+	       (!!(PQ_FLAGS_OFLD & pq_flags)) *
+	       qed_init_qm_get_num_mtc_tcs(p_hwfn) +
+	       (!!(PQ_FLAGS_LLT & pq_flags)) *
+	       qed_init_qm_get_num_mtc_tcs(p_hwfn) +
 	       (!!(PQ_FLAGS_VFS & pq_flags)) * qed_init_qm_get_num_vfs(p_hwfn);
 }
 
@@ -474,9 +489,9 @@ static u16 *qed_init_qm_get_idx_from_flags(struct qed_hwfn *p_hwfn,
 	case PQ_FLAGS_ACK:
 		return &qm_info->pure_ack_pq;
 	case PQ_FLAGS_OFLD:
-		return &qm_info->offload_pq;
+		return &qm_info->first_ofld_pq;
 	case PQ_FLAGS_LLT:
-		return &qm_info->low_latency_pq;
+		return &qm_info->first_llt_pq;
 	case PQ_FLAGS_VFS:
 		return &qm_info->first_vf_pq;
 	default:
@@ -525,6 +540,28 @@ u16 qed_get_cm_pq_idx_vf(struct qed_hwfn *p_hwfn, u16 vf)
 	return qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_VFS) + vf;
 }
 
+u16 qed_get_cm_pq_idx_ofld_mtc(struct qed_hwfn *p_hwfn, u8 tc)
+{
+	u16 first_ofld_pq, pq_offset;
+
+	first_ofld_pq = qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_OFLD);
+	pq_offset = (tc < qed_init_qm_get_num_mtc_tcs(p_hwfn)) ?
+		    tc : PQ_INIT_DEFAULT_TC;
+
+	return first_ofld_pq + pq_offset;
+}
+
+u16 qed_get_cm_pq_idx_llt_mtc(struct qed_hwfn *p_hwfn, u8 tc)
+{
+	u16 first_llt_pq, pq_offset;
+
+	first_llt_pq = qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_LLT);
+	pq_offset = (tc < qed_init_qm_get_num_mtc_tcs(p_hwfn)) ?
+		    tc : PQ_INIT_DEFAULT_TC;
+
+	return first_llt_pq + pq_offset;
+}
+
 /* Functions for creating specific types of pqs */
 static void qed_init_qm_lb_pq(struct qed_hwfn *p_hwfn)
 {
@@ -560,6 +597,20 @@ static void qed_init_qm_pure_ack_pq(struct qed_hwfn *p_hwfn)
 		       PQ_INIT_SHARE_VPORT);
 }
 
+static void qed_init_qm_mtc_pqs(struct qed_hwfn *p_hwfn)
+{
+	u8 num_tcs = qed_init_qm_get_num_mtc_tcs(p_hwfn);
+	struct qed_qm_info *qm_info = &p_hwfn->qm_info;
+	u8 tc;
+
+	/* override pq's TC if offload TC is set */
+	for (tc = 0; tc < num_tcs; tc++)
+		qed_init_qm_pq(p_hwfn, qm_info,
+			       qed_is_offload_tc_set(p_hwfn) ?
+			       p_hwfn->hw_info.offload_tc : tc,
+			       PQ_INIT_SHARE_VPORT);
+}
+
 static void qed_init_qm_offload_pq(struct qed_hwfn *p_hwfn)
 {
 	struct qed_qm_info *qm_info = &p_hwfn->qm_info;
@@ -568,8 +619,7 @@ static void qed_init_qm_offload_pq(struct qed_hwfn *p_hwfn)
 		return;
 
 	qed_init_qm_set_idx(p_hwfn, PQ_FLAGS_OFLD, qm_info->num_pqs);
-	qed_init_qm_pq(p_hwfn, qm_info, qed_get_offload_tc(p_hwfn),
-		       PQ_INIT_SHARE_VPORT);
+	qed_init_qm_mtc_pqs(p_hwfn);
 }
 
 static void qed_init_qm_low_latency_pq(struct qed_hwfn *p_hwfn)
@@ -580,8 +630,7 @@ static void qed_init_qm_low_latency_pq(struct qed_hwfn *p_hwfn)
 		return;
 
 	qed_init_qm_set_idx(p_hwfn, PQ_FLAGS_LLT, qm_info->num_pqs);
-	qed_init_qm_pq(p_hwfn, qm_info, qed_get_offload_tc(p_hwfn),
-		       PQ_INIT_SHARE_VPORT);
+	qed_init_qm_mtc_pqs(p_hwfn);
 }
 
 static void qed_init_qm_mcos_pqs(struct qed_hwfn *p_hwfn)
@@ -664,12 +713,19 @@ static int qed_init_qm_sanity(struct qed_hwfn *p_hwfn)
 		return -EINVAL;
 	}
 
-	if (qed_init_qm_get_num_pqs(p_hwfn) > RESC_NUM(p_hwfn, QED_PQ)) {
-		DP_ERR(p_hwfn, "requested amount of pqs exceeds resource\n");
-		return -EINVAL;
+	if (qed_init_qm_get_num_pqs(p_hwfn) <= RESC_NUM(p_hwfn, QED_PQ))
+		return 0;
+
+	if (QED_IS_ROCE_PERSONALITY(p_hwfn)) {
+		p_hwfn->hw_info.multi_tc_roce_en = 0;
+		DP_NOTICE(p_hwfn,
+			  "multi-tc roce was disabled to reduce requested amount of pqs\n");
+		if (qed_init_qm_get_num_pqs(p_hwfn) <= RESC_NUM(p_hwfn, QED_PQ))
+			return 0;
 	}
 
-	return 0;
+	DP_ERR(p_hwfn, "requested amount of pqs exceeds resource\n");
+	return -EINVAL;
 }
 
 static void qed_dp_init_qm_params(struct qed_hwfn *p_hwfn)
@@ -683,11 +739,13 @@ static void qed_dp_init_qm_params(struct qed_hwfn *p_hwfn)
 	/* top level params */
 	DP_VERBOSE(p_hwfn,
 		   NETIF_MSG_HW,
-		   "qm init top level params: start_pq %d, start_vport %d, pure_lb_pq %d, offload_pq %d, pure_ack_pq %d\n",
+		   "qm init top level params: start_pq %d, start_vport %d, pure_lb_pq %d, offload_pq %d, llt_pq %d, pure_ack_pq %d\n",
 		   qm_info->start_pq,
 		   qm_info->start_vport,
 		   qm_info->pure_lb_pq,
-		   qm_info->offload_pq, qm_info->pure_ack_pq);
+		   qm_info->first_ofld_pq,
+		   qm_info->first_llt_pq,
+		   qm_info->pure_ack_pq);
 	DP_VERBOSE(p_hwfn,
 		   NETIF_MSG_HW,
 		   "ooo_pq %d, first_vf_pq %d, num_pqs %d, num_vf_pqs %d, num_vports %d, max_phys_tcs_per_port %d\n",
@@ -2920,6 +2978,9 @@ static void qed_get_eee_caps(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 		p_hwfn->hw_info.personality = protocol;
 	}
 
+	if (QED_IS_ROCE_PERSONALITY(p_hwfn))
+		p_hwfn->hw_info.multi_tc_roce_en = 1;
+
 	p_hwfn->hw_info.num_hw_tc = NUM_PHYS_TCS_4PORT_K2;
 	p_hwfn->hw_info.num_active_tc = 1;
 
diff --git a/drivers/net/ethernet/qlogic/qed/qed_roce.c b/drivers/net/ethernet/qlogic/qed/qed_roce.c
index ada4c18..7d7a64c 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_roce.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_roce.c
@@ -44,8 +44,10 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
+#include <linux/if_vlan.h>
 #include "qed.h"
 #include "qed_cxt.h"
+#include "qed_dcbx.h"
 #include "qed_hsi.h"
 #include "qed_hw.h"
 #include "qed_init_ops.h"
@@ -231,16 +233,33 @@ static void qed_roce_set_real_cid(struct qed_hwfn *p_hwfn, u32 cid)
 	spin_unlock_bh(&p_hwfn->p_rdma_info->lock);
 }
 
+static u8 qed_roce_get_qp_tc(struct qed_hwfn *p_hwfn, struct qed_rdma_qp *qp)
+{
+	u8 pri, tc = 0;
+
+	if (qp->vlan_id) {
+		pri = (qp->vlan_id & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+		tc = qed_dcbx_get_priority_tc(p_hwfn, pri);
+	}
+
+	DP_VERBOSE(p_hwfn, QED_MSG_SP,
+		   "qp icid %u tc: %u (vlan priority %s)\n",
+		   qp->icid, tc, qp->vlan_id ? "enabled" : "disabled");
+
+	return tc;
+}
+
 static int qed_roce_sp_create_responder(struct qed_hwfn *p_hwfn,
 					struct qed_rdma_qp *qp)
 {
 	struct roce_create_qp_resp_ramrod_data *p_ramrod;
+	u16 regular_latency_queue, low_latency_queue;
 	struct qed_sp_init_data init_data;
 	enum roce_flavor roce_flavor;
 	struct qed_spq_entry *p_ent;
-	u16 regular_latency_queue;
 	enum protocol_type proto;
 	int rc;
+	u8 tc;
 
 	DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "icid = %08x\n", qp->icid);
 
@@ -324,12 +343,17 @@ static int qed_roce_sp_create_responder(struct qed_hwfn *p_hwfn,
 	p_ramrod->cq_cid = cpu_to_le32((p_hwfn->hw_info.opaque_fid << 16) |
 				       qp->rq_cq_id);
 
-	regular_latency_queue = qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_OFLD);
-
+	tc = qed_roce_get_qp_tc(p_hwfn, qp);
+	regular_latency_queue = qed_get_cm_pq_idx_ofld_mtc(p_hwfn, tc);
+	low_latency_queue = qed_get_cm_pq_idx_llt_mtc(p_hwfn, tc);
+	DP_VERBOSE(p_hwfn, QED_MSG_SP,
+		   "qp icid %u pqs: regular_latency %u low_latency %u\n",
+		   qp->icid, regular_latency_queue - CM_TX_PQ_BASE,
+		   low_latency_queue - CM_TX_PQ_BASE);
 	p_ramrod->regular_latency_phy_queue =
 	    cpu_to_le16(regular_latency_queue);
 	p_ramrod->low_latency_phy_queue =
-	    cpu_to_le16(regular_latency_queue);
+	    cpu_to_le16(low_latency_queue);
 
 	p_ramrod->dpi = cpu_to_le16(qp->dpi);
 
@@ -345,11 +369,6 @@ static int qed_roce_sp_create_responder(struct qed_hwfn *p_hwfn,
 				     qp->stats_queue;
 
 	rc = qed_spq_post(p_hwfn, p_ent, NULL);
-
-	DP_VERBOSE(p_hwfn, QED_MSG_RDMA,
-		   "rc = %d regular physical queue = 0x%x\n", rc,
-		   regular_latency_queue);
-
 	if (rc)
 		goto err;
 
@@ -375,12 +394,13 @@ static int qed_roce_sp_create_requester(struct qed_hwfn *p_hwfn,
 					struct qed_rdma_qp *qp)
 {
 	struct roce_create_qp_req_ramrod_data *p_ramrod;
+	u16 regular_latency_queue, low_latency_queue;
 	struct qed_sp_init_data init_data;
 	enum roce_flavor roce_flavor;
 	struct qed_spq_entry *p_ent;
-	u16 regular_latency_queue;
 	enum protocol_type proto;
 	int rc;
+	u8 tc;
 
 	DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "icid = %08x\n", qp->icid);
 
@@ -453,12 +473,17 @@ static int qed_roce_sp_create_requester(struct qed_hwfn *p_hwfn,
 	p_ramrod->cq_cid =
 	    cpu_to_le32((p_hwfn->hw_info.opaque_fid << 16) | qp->sq_cq_id);
 
-	regular_latency_queue = qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_OFLD);
-
+	tc = qed_roce_get_qp_tc(p_hwfn, qp);
+	regular_latency_queue = qed_get_cm_pq_idx_ofld_mtc(p_hwfn, tc);
+	low_latency_queue = qed_get_cm_pq_idx_llt_mtc(p_hwfn, tc);
+	DP_VERBOSE(p_hwfn, QED_MSG_SP,
+		   "qp icid %u pqs: regular_latency %u low_latency %u\n",
+		   qp->icid, regular_latency_queue - CM_TX_PQ_BASE,
+		   low_latency_queue - CM_TX_PQ_BASE);
 	p_ramrod->regular_latency_phy_queue =
 	    cpu_to_le16(regular_latency_queue);
 	p_ramrod->low_latency_phy_queue =
-	    cpu_to_le16(regular_latency_queue);
+	    cpu_to_le16(low_latency_queue);
 
 	p_ramrod->dpi = cpu_to_le16(qp->dpi);
 
@@ -471,9 +496,6 @@ static int qed_roce_sp_create_requester(struct qed_hwfn *p_hwfn,
 				     qp->stats_queue;
 
 	rc = qed_spq_post(p_hwfn, p_ent, NULL);
-
-	DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "rc = %d\n", rc);
-
 	if (rc)
 		goto err;
 
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net-next v3 0/3] qed: Add Multi-TC RoCE support
From: Denis Bolotin @ 2018-08-07 12:48 UTC (permalink / raw)
  To: davem, netdev; +Cc: Denis Bolotin

Hi Dave,
This patch series adds support for multiple concurrent traffic classes for RoCE.
The first three patches enable the required parts of the driver to learn the TC
configuration, and the last one makes use of it to enable the feature.
Please consider applying this to net-next.

V1->V2:
-------
Avoid allocation in qed_dcbx_get_priority_tc().
Move qed_dcbx_get_priority_tc() out of CONFIG_DCB section since it doesn't call
qed_dcbx_query_params() anymore.

v2->V3:
-------
patch 1/3:
qed_dcbx_get_priority_tc() always returns a valid TC by value. In error cases,
it returns QED_DCBX_DEFAULT_TC (currently defined 0).
patch 3/3:
Cosmetic changes in qed_dev.c.

Denis Bolotin (3):
  qed: Add DCBX API - qed_dcbx_get_priority_tc()
  qed: Add a flag which indicates if offload TC is set
  qed: Add Multi-TC RoCE support

 drivers/net/ethernet/qlogic/qed/qed.h      |  13 +++-
 drivers/net/ethernet/qlogic/qed/qed_dcbx.c |  20 ++++-
 drivers/net/ethernet/qlogic/qed/qed_dcbx.h |   3 +
 drivers/net/ethernet/qlogic/qed/qed_dev.c  | 113 +++++++++++++++++++++++++----
 drivers/net/ethernet/qlogic/qed/qed_mcp.c  |   3 +-
 drivers/net/ethernet/qlogic/qed/qed_roce.c |  54 ++++++++++----
 6 files changed, 171 insertions(+), 35 deletions(-)

-- 
1.8.3.1

^ permalink raw reply

* Re: [PATCH 4.9-stable] tcp: add tcp_ooo_try_coalesce() helper
From: Greg KH @ 2018-08-07 13:22 UTC (permalink / raw)
  To: David Woodhouse
  Cc: davem, edumazet, juha-matti.tilli, ycheng, soheil, netdev,
	eric.dumazet, dwmw2, jdw
In-Reply-To: <1533373800-22712-1-git-send-email-dwmw@amazon.co.uk>

On Sat, Aug 04, 2018 at 10:10:00AM +0100, David Woodhouse wrote:
> From: Eric Dumazet <edumazet@google.com>
> 
> commit 58152ecbbcc6a0ce7fddd5bf5f6ee535834ece0c upstream.
> 
> In case skb in out_or_order_queue is the result of
> multiple skbs coalescing, we would like to get a proper gso_segs
> counter tracking, so that future tcp_drop() can report an accurate
> number.
> 
> I chose to not implement this tracking for skbs in receive queue,
> since they are not dropped, unless socket is disconnected.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Acked-by: Soheil Hassas Yeganeh <soheil@google.com>
> Acked-by: Yuchung Cheng <ycheng@google.com>
> Signed-off-by: David S. Miller <davem@davemloft.net>
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> ---
>  net/ipv4/tcp_input.c | 23 +++++++++++++++++++++--
>  1 file changed, 21 insertions(+), 2 deletions(-)

Now applied, thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH RFC net-next] openvswitch: Queue upcalls to userspace in per-port round-robin order
From: Stefano Brivio @ 2018-08-07 13:31 UTC (permalink / raw)
  To: Pravin Shelar
  Cc: Matteo Croce, Justin Pettit, Greg Rose, Ben Pfaff, netdev,
	ovs dev, Jiri Benc, Aaron
In-Reply-To: <CAOrHB_B4qhwMuhWFhQco+pPyPxcSpOPswMpNyEEq2n+mET-mXA@mail.gmail.com>

Hi Pravin,

On Tue, 31 Jul 2018 16:12:03 -0700
Pravin Shelar <pshelar@ovn.org> wrote:

> Rather than reducing number of thread down to 1, we could find better
> number of FDs per port.
> How about this simple solution:
> 1. Allocate (N * P) FDs as long as it is under FD limit.
> 2. If FD limit (-EMFILE) is hit reduce N value by half and repeat step 1.

I still see a few quantitative issues with this approach, other than
Ben's observation about design (which, by the way, looks entirely
reasonable to me).

We're talking about a disproportionate amount of sockets in any case.
We can have up to 2^16 vports here, with 5k vports being rather common,
and for any reasonable value of N that manages somehow to perturbate the
distribution of upcalls per thread, we are talking about something well
in excess of 100k sockets. I think this doesn't really scale.

With the current value for N (3/4 * number of threads) this can even get
close to /proc/sys/fs/file-max on some systems, and there raising the
number of allowed file descriptors for ovs-vswitchd isn't a solution
anymore.

I would instead try to address the concerns that you had about the
original patch adding fairness in the kernel, rather than trying to
make the issue appear less severe in ovs-vswitchd.

-- 
Stefano

^ permalink raw reply

* Re: [PATCH v3 net-next 5/9] net: stmmac: Add MDIO related functions for XGMAC2
From: Jose Abreu @ 2018-08-07 13:35 UTC (permalink / raw)
  To: Florian Fainelli, Jose Abreu, netdev
  Cc: David S. Miller, Joao Pinto, Giuseppe Cavallaro, Alexandre Torgue,
	Andrew Lunn
In-Reply-To: <C540FD04-8429-41E3-9C2C-C21CEAF8030D@gmail.com>

Hi Florian,

On 06-08-2018 16:25, Florian Fainelli wrote:
> On August 6, 2018 12:59:54 AM PDT, Jose Abreu <Jose.Abreu@synopsys.com> wrote:
>> On 03-08-2018 20:06, Florian Fainelli wrote:
>>> On 08/03/2018 08:50 AM, Jose Abreu wrote:
>>>> Add the MDIO related funcionalities for the new IP block XGMAC2.
>>>>
>>>> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
>>>> Cc: David S. Miller <davem@davemloft.net>
>>>> Cc: Joao Pinto <jpinto@synopsys.com>
>>>> Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
>>>> Cc: Alexandre Torgue <alexandre.torgue@st.com>
>>>> Cc: Andrew Lunn <andrew@lunn.ch>
>>>> ---
>>>> +satic int stmmac_xgmac2_c22_format(struct stmmac_priv *priv, int
>> phyaddr,
>>>> +				    int phyreg, u32 *hw_addr)
>>>> +{
>>>> +	unsigned int mii_data = priv->hw->mii.data;
>>>> +	u32 tmp;
>>>> +
>>>> +	/* HW does not support C22 addr >= 4 */
>>>> +	if (phyaddr >= 4)
>>>> +		return -ENODEV;
>>> It would be nice if this could be moved at probe time so you don't
>> have
>>> to wait until you connect to the PHY, read its PHY OUI and find out
>> it
>>> has a MDIO address >= 4. Not a blocker, but something that could be
>>> improved further on.
>>>
>>> In premise you could even scan the MDIO bus' device tree node, and
>> find
>>> that out ahead of time.
>> Oh, but I use phylib ... I only provide the read/write callbacks
>> so I think we should avoid duplicating the code that's already in
>> the phylib ... No?
> You can always extract the code that scans a MDIO bus into a helper function and make it parametrized with a callback of some kind. In that case I would be fine with you open coding the MDIO bus scan to find out if there is an address >= 4.

Sorry but I dont' think thats the best solution because
of_mdiobus_register() already scans the bus. Duplicating this
should be avoided, no?

Note all of this is probably never needed because stmmac just
picks the first phy it finds, if phy_addr is not specified ...

>
>>>> +	/* Wait until any existing MII operation is complete */
>>>> +	if (readl_poll_timeout(priv->ioaddr + mii_data, tmp,
>>>> +			       !(tmp & MII_XGMAC_BUSY), 100, 10000))
>>>> +		return -EBUSY;
>>>> +
>>>> +	/* Set port as Clause 22 */
>>>> +	tmp = readl(priv->ioaddr + XGMAC_MDIO_C22P);
>>>> +	tmp |= BIT(phyaddr);
>>> Since the registers are being Read/Modify/Write here, don't you need
>> to
>>> clear the previous address bits as well?
>>>
>>> You probably did not encounter any problems in your testing if you
>> had
>>> only one PHY on the MDIO bus, but this is not something that is
>>> necessarily true, e.g: if you have an Ethernet switch, several MDIO
>> bus
>>> addresses are going to be responding.
>>>
>>> Your MDIO bus implementation must be able to support one transaction
>>> with one PHY address and the next transaction with another PHY
>> address ,
>>> etc...
>>>
>>> That is something that should be easy to fix and be resubmitted as
>> part
>>> of v4.
>> I'm not following you here... I only set/unset the bit for the
>> corresponding phyaddr that phylib wants to read/write. Why would
>> I clear the remaining addresses?
> Because this is all about transactions, the HW must be in a state that it will be able to perform that transaction correctly. So here for instance if you needed to support a C45 transaction you would have to clear that bit for that particular PHY address. Since you don't appear to support those yet then yes the code appears fine though it would not hurt if you did clear all other PHY's c22 bits to make it clear what this does.

I can't test C45 right now but I will in a near future. In that
case then we will need to support C22 and C45 so I may want to
only set one bit for a specific phy that only supports c22.

Thanks and Best Regards,
Jose Miguel Abreu

>

^ permalink raw reply

* Re: [PATCH RFC net-next] openvswitch: Queue upcalls to userspace in per-port round-robin order
From: Stefano Brivio @ 2018-08-07 13:39 UTC (permalink / raw)
  To: Pravin Shelar
  Cc: Matteo Croce, Justin Pettit, Greg Rose, Ben Pfaff, netdev,
	ovs dev, Jiri Benc, Aaron
In-Reply-To: <20180807153111.53b0da8d@epycfail>

On Tue, 7 Aug 2018 15:31:11 +0200
Stefano Brivio <sbrivio@redhat.com> wrote:

> I would instead try to address the concerns that you had about the
> original patch adding fairness in the kernel, rather than trying to
> make the issue appear less severe in ovs-vswitchd.

And, by the way, if we introduce a way to configure the possible
fairness algorithms via netlink, we can also rather easily allow
ovs-vswitchd to disable fairness on kernel side altogether, should it
be needed.

-- 
Stefano

^ permalink raw reply

* Re: [PATCH bpf-next 1/3] bpf: add bpf queue map
From: Daniel Borkmann @ 2018-08-07 13:40 UTC (permalink / raw)
  To: Mauricio Vasquez B, Alexei Starovoitov; +Cc: netdev
In-Reply-To: <153356390770.6981.4228793745105954649.stgit@kernel>

On 08/06/2018 03:58 PM, Mauricio Vasquez B wrote:
> Bpf queue implements a LIFO/FIFO data containers for ebpf programs.
> 
> It allows to push an element to the queue by using the update operation
> and to pop an element from the queue by using the lookup operation.
> 
> A use case for this is to keep track of a pool of elements, like
> network ports in a SNAT.
> 
> Signed-off-by: Mauricio Vasquez B <mauricio.vasquez@polito.it>
> ---
>  include/linux/bpf_types.h |    1 
>  include/uapi/linux/bpf.h  |    5 +
>  kernel/bpf/Makefile       |    2 
>  kernel/bpf/queuemap.c     |  287 +++++++++++++++++++++++++++++++++++++++++++++
>  kernel/bpf/syscall.c      |   61 +++++++---
>  kernel/bpf/verifier.c     |   16 ++-
>  6 files changed, 353 insertions(+), 19 deletions(-)
>  create mode 100644 kernel/bpf/queuemap.c
> 
> diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h
> index c5700c2d5549..6c7a62f3fe43 100644
> --- a/include/linux/bpf_types.h
> +++ b/include/linux/bpf_types.h
> @@ -58,3 +58,4 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_CPUMAP, cpu_map_ops)
>  BPF_MAP_TYPE(BPF_MAP_TYPE_XSKMAP, xsk_map_ops)
>  #endif
>  #endif
> +BPF_MAP_TYPE(BPF_MAP_TYPE_QUEUE, queue_map_ops)
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index 0ebaaf7f3568..2c171c40eb45 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -120,6 +120,7 @@ enum bpf_map_type {
>  	BPF_MAP_TYPE_CPUMAP,
>  	BPF_MAP_TYPE_XSKMAP,
>  	BPF_MAP_TYPE_SOCKHASH,
> +	BPF_MAP_TYPE_QUEUE,
>  };
>  
>  enum bpf_prog_type {
> @@ -255,6 +256,10 @@ enum bpf_attach_type {
>  /* Flag for stack_map, store build_id+offset instead of pointer */
>  #define BPF_F_STACK_BUILD_ID	(1U << 5)
>  
> +/* Flags for queue_map, type of queue */
> +#define BPF_F_QUEUE_FIFO	(1U << 16)
> +#define BPF_F_QUEUE_LIFO	(2U << 16)
> +
>  enum bpf_stack_build_id_status {
>  	/* user space need an empty entry to identify end of a trace */
>  	BPF_STACK_BUILD_ID_EMPTY = 0,
> diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile
> index f27f5496d6fe..30f02ef66635 100644
> --- a/kernel/bpf/Makefile
> +++ b/kernel/bpf/Makefile
> @@ -2,7 +2,7 @@
>  obj-y := core.o
>  
>  obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o
> -obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o lpm_trie.o map_in_map.o
> +obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o lpm_trie.o map_in_map.o queuemap.o
>  obj-$(CONFIG_BPF_SYSCALL) += disasm.o
>  obj-$(CONFIG_BPF_SYSCALL) += btf.o
>  ifeq ($(CONFIG_NET),y)
> diff --git a/kernel/bpf/queuemap.c b/kernel/bpf/queuemap.c
> new file mode 100644
> index 000000000000..ab30af43b4cc
> --- /dev/null
> +++ b/kernel/bpf/queuemap.c
> @@ -0,0 +1,287 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * queuemap.c: BPF queue map
> + *
> + * Copyright (c) 2018 Politecnico di Torino
> + */
> +#include <linux/bpf.h>
> +#include <linux/rculist.h>
> +#include <linux/slab.h>
> +#include "percpu_freelist.h"
> +
> +#define QUEUE_CREATE_FLAG_MASK \
> +	(BPF_F_NO_PREALLOC | BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY | \
> +	 BPF_F_QUEUE_FIFO | BPF_F_QUEUE_LIFO)
> +
> +enum queue_type {
> +	QUEUE_FIFO = (BPF_F_QUEUE_FIFO >> 16),
> +	QUEUE_LIFO = (BPF_F_QUEUE_LIFO >> 16),
> +};
> +
> +struct bpf_queue {
> +	struct bpf_map map;
> +	struct list_head head;
> +	struct pcpu_freelist freelist;
> +	void *nodes;
> +	enum queue_type type;
> +	raw_spinlock_t lock;
> +	atomic_t count;
> +	u32 node_size;
> +};
> +
> +struct queue_node {
> +	struct pcpu_freelist_node fnode;
> +	struct bpf_queue *queue;
> +	struct list_head list;
> +	struct rcu_head rcu;
> +	char element[0] __aligned(8);
> +};
> +
> +static bool queue_map_is_prealloc(struct bpf_queue *queue)
> +{
> +	return !(queue->map.map_flags & BPF_F_NO_PREALLOC);
> +}
> +
> +/* Called from syscall */
> +static int queue_map_alloc_check(union bpf_attr *attr)
> +{
> +	/* check sanity of attributes */
> +	if (attr->max_entries == 0 || attr->key_size != 0 ||
> +	    attr->value_size == 0 || attr->map_flags & ~QUEUE_CREATE_FLAG_MASK)
> +		return -EINVAL;
> +
> +	if ((attr->map_flags >> 16) != QUEUE_FIFO &&
> +	    (attr->map_flags >> 16) != QUEUE_LIFO) {
> +		return -EINVAL;
> +	}
> +
> +	if (attr->value_size > KMALLOC_MAX_SIZE)
> +		/* if value_size is bigger, the user space won't be able to
> +		 * access the elements.
> +		 */
> +		return -E2BIG;
> +
> +	return 0;
> +}
> +
> +static int prealloc_init(struct bpf_queue *queue)
> +{
> +	u32 node_size = sizeof(struct queue_node) +
> +			round_up(queue->map.value_size, 8);
> +	u32 num_entries = queue->map.max_entries;
> +	int err;
> +
> +	queue->nodes = bpf_map_area_alloc(node_size * num_entries,
> +					  queue->map.numa_node);
> +	if (!queue->nodes)
> +		return -ENOMEM;
> +
> +	err = pcpu_freelist_init(&queue->freelist);
> +	if (err)
> +		goto free_nodes;
> +
> +	pcpu_freelist_populate(&queue->freelist,
> +			       queue->nodes +
> +			       offsetof(struct queue_node, fnode),
> +			       node_size, num_entries);
> +
> +	return 0;
> +
> +free_nodes:
> +	bpf_map_area_free(queue->nodes);
> +	return err;
> +}
> +
> +static void prealloc_destroy(struct bpf_queue *queue)
> +{
> +	bpf_map_area_free(queue->nodes);
> +	pcpu_freelist_destroy(&queue->freelist);
> +}
> +
> +static struct bpf_map *queue_map_alloc(union bpf_attr *attr)
> +{
> +	struct bpf_queue *queue;
> +	u64 cost = sizeof(*queue);
> +	int ret;
> +
> +	queue = kzalloc(sizeof(*queue), GFP_USER);
> +	if (!queue)
> +		return ERR_PTR(-ENOMEM);
> +
> +	bpf_map_init_from_attr(&queue->map, attr);
> +
> +	queue->node_size = sizeof(struct queue_node) +
> +			   round_up(attr->value_size, 8);
> +	cost += (u64) attr->max_entries * queue->node_size;
> +	if (cost >= U32_MAX - PAGE_SIZE) {
> +		ret = -E2BIG;
> +		goto free_queue;
> +	}
> +
> +	queue->map.pages = round_up(cost, PAGE_SIZE) >> PAGE_SHIFT;
> +
> +	ret = bpf_map_precharge_memlock(queue->map.pages);
> +	if (ret)
> +		goto free_queue;
> +
> +	INIT_LIST_HEAD(&queue->head);
> +
> +	raw_spin_lock_init(&queue->lock);
> +
> +	queue->type = attr->map_flags >> 16;
> +
> +	if (queue_map_is_prealloc(queue))
> +		ret = prealloc_init(queue);
> +		if (ret)
> +			goto free_queue;
> +
> +	return &queue->map;
> +
> +free_queue:
> +	kfree(queue);
> +	return ERR_PTR(ret);
> +}
> +
> +/* Called when map->refcnt goes to zero, either from workqueue or from syscall */
> +static void queue_map_free(struct bpf_map *map)
> +{
> +	struct bpf_queue *queue = container_of(map, struct bpf_queue, map);
> +	struct queue_node *l;
> +
> +	/* at this point bpf_prog->aux->refcnt == 0 and this map->refcnt == 0,
> +	 * so the programs (can be more than one that used this map) were
> +	 * disconnected from events. Wait for outstanding critical sections in
> +	 * these programs to complete
> +	 */
> +	synchronize_rcu();
> +
> +	/* some of queue_elem_free_rcu() callbacks for elements of this map may
> +	 * not have executed. Wait for them.
> +	 */
> +	rcu_barrier();
> +	if (!queue_map_is_prealloc(queue))
> +		list_for_each_entry_rcu(l, &queue->head, list) {
> +			list_del_rcu(&l->list);
> +			kfree(l);
> +		}
> +	else
> +		prealloc_destroy(queue);
> +	kfree(queue);
> +}
> +
> +static void queue_elem_free_rcu(struct rcu_head *head)
> +{
> +	struct queue_node *l = container_of(head, struct queue_node, rcu);
> +	struct bpf_queue *queue = l->queue;
> +
> +	/* must increment bpf_prog_active to avoid kprobe+bpf triggering while
> +	 * we're calling kfree, otherwise deadlock is possible if kprobes
> +	 * are placed somewhere inside of slub
> +	 */
> +	preempt_disable();
> +	__this_cpu_inc(bpf_prog_active);
> +	if (queue_map_is_prealloc(queue))
> +		pcpu_freelist_push(&queue->freelist, &l->fnode);
> +	else
> +		kfree(l);
> +	__this_cpu_dec(bpf_prog_active);
> +	preempt_enable();
> +}
> +
> +/* Called from syscall or from eBPF program */
> +static void *queue_map_lookup_elem(struct bpf_map *map, void *key)
> +{
> +	struct bpf_queue *queue = container_of(map, struct bpf_queue, map);
> +	unsigned long flags;
> +	struct queue_node *node;
> +
> +	raw_spin_lock_irqsave(&queue->lock, flags);

I think a per-cpu flavor would be very useful here as well in this map
type such that we wouldn't need a lock here but only guarantee that
preemption is disabled, and it could be used as temp store for the program
for example.

> +	node = list_first_or_null_rcu(&queue->head, struct queue_node, list);
> +	if (!node) {
> +		raw_spin_unlock_irqrestore(&queue->lock, flags);
> +		return NULL;
> +	}
> +
> +	if (!queue_map_is_prealloc(queue))
> +		atomic_dec(&queue->count);
> +
> +	list_del_rcu(&node->list);
> +	call_rcu(&node->rcu, queue_elem_free_rcu);
> +
> +	raw_spin_unlock_irqrestore(&queue->lock, flags);
> +
> +	return &node->element;
> +}
> +
> +/* Called from syscall or from eBPF program */
> +static int queue_map_update_elem(struct bpf_map *map, void *key, void *value,
> +				 u64 map_flags)
> +{
> +	struct bpf_queue *queue = container_of(map, struct bpf_queue, map);
> +	unsigned long flags;
> +	struct queue_node *new;

Should reject invalid map update flags here.

> +	if (!queue_map_is_prealloc(queue)) {
> +		if (atomic_inc_return(&queue->count) > queue->map.max_entries) {
> +			atomic_dec(&queue->count);
> +			return -E2BIG;
> +		}
> +
> +		new = kmalloc_node(queue->node_size, GFP_ATOMIC | __GFP_NOWARN,
> +				   queue->map.numa_node);
> +		if (!new) {
> +			atomic_dec(&queue->count);
> +			return -ENOMEM;
> +		}
> +	} else {
> +		struct pcpu_freelist_node *l;
> +
> +		l = pcpu_freelist_pop(&queue->freelist);
> +		if (!l)
> +			return -E2BIG;
> +		new = container_of(l, struct queue_node, fnode);
> +	}
> +
> +	memcpy(new->element, value, queue->map.value_size);
> +	new->queue = queue;
> +
> +	raw_spin_lock_irqsave(&queue->lock, flags);
> +	switch (queue->type) {
> +	case QUEUE_FIFO:
> +		list_add_tail_rcu(&new->list, &queue->head);
> +		break;
> +
> +	case QUEUE_LIFO:
> +		list_add_rcu(&new->list, &queue->head);
> +		break;
> +	}
> +
> +	raw_spin_unlock_irqrestore(&queue->lock, flags);
> +
> +	return 0;
> +}
> +
> +/* Called from syscall or from eBPF program */
> +static int queue_map_delete_elem(struct bpf_map *map, void *key)
> +{
> +	return -EINVAL;
> +}
> +
> +/* Called from syscall */
> +static int queue_map_get_next_key(struct bpf_map *map, void *key,
> +				  void *next_key)
> +{
> +	return -EINVAL;
> +}
> +
> +const struct bpf_map_ops queue_map_ops = {
> +	.map_alloc_check = queue_map_alloc_check,
> +	.map_alloc = queue_map_alloc,
> +	.map_free = queue_map_free,
> +	.map_lookup_elem = queue_map_lookup_elem,
> +	.map_update_elem = queue_map_update_elem,
> +	.map_delete_elem = queue_map_delete_elem,
> +	.map_get_next_key = queue_map_get_next_key,
> +};
> +
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index a31a1ba0f8ea..7e9a11d69eef 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -622,11 +622,19 @@ static int map_lookup_elem(union bpf_attr *attr)
>  		err = -EPERM;
>  		goto err_put;
>  	}
> +	if (map->map_type != BPF_MAP_TYPE_QUEUE) {
> +		key = memdup_user(ukey, map->key_size);
> +		if (IS_ERR(key)) {
> +			err = PTR_ERR(key);
> +			goto err_put;
> +		}
> +	} else {
> +		if (ukey) {
> +			err = -EINVAL;
> +			goto err_put;
> +		}

Given you have a fixed key_size of 0, this could probably be made more
generic and refactored a bit into a helper to check for 0 map->key_size
instead of map type.

> -	key = memdup_user(ukey, map->key_size);
> -	if (IS_ERR(key)) {
> -		err = PTR_ERR(key);
> -		goto err_put;
> +		key = NULL;
>  	}
>  
>  	if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
> @@ -709,10 +717,19 @@ static int map_update_elem(union bpf_attr *attr)
>  		goto err_put;
>  	}
>  
> -	key = memdup_user(ukey, map->key_size);
> -	if (IS_ERR(key)) {
> -		err = PTR_ERR(key);
> -		goto err_put;
> +	if (map->map_type != BPF_MAP_TYPE_QUEUE) {
> +		key = memdup_user(ukey, map->key_size);
> +		if (IS_ERR(key)) {
> +			err = PTR_ERR(key);
> +			goto err_put;
> +		}
> +	} else {
> +		if (ukey) {
> +			err = -EINVAL;
> +			goto err_put;
> +		}
> +
> +		key = NULL;
>  	}

Ditto, and also further below as well for the other syscall cases.

>  
>  	if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
> @@ -803,10 +820,19 @@ static int map_delete_elem(union bpf_attr *attr)
>  		goto err_put;
>  	}
>  
> -	key = memdup_user(ukey, map->key_size);
> -	if (IS_ERR(key)) {
> -		err = PTR_ERR(key);
> -		goto err_put;
> +	if (map->map_type != BPF_MAP_TYPE_QUEUE) {
> +		key = memdup_user(ukey, map->key_size);
> +		if (IS_ERR(key)) {
> +			err = PTR_ERR(key);
> +			goto err_put;
> +		}
> +	} else {
> +		if (ukey) {
> +			err = -EINVAL;
> +			goto err_put;
> +		}
> +
> +		key = NULL;
>  	}
>  
>  	if (bpf_map_is_dev_bound(map)) {
> @@ -855,9 +881,14 @@ static int map_get_next_key(union bpf_attr *attr)
>  	}
>  
>  	if (ukey) {
> -		key = memdup_user(ukey, map->key_size);
> -		if (IS_ERR(key)) {
> -			err = PTR_ERR(key);
> +		if (map->map_type != BPF_MAP_TYPE_QUEUE) {
> +			key = memdup_user(ukey, map->key_size);
> +			if (IS_ERR(key)) {
> +				err = PTR_ERR(key);
> +				goto err_put;
> +			}
> +		} else {
> +			err = -EINVAL;
>  			goto err_put;
>  		}
>  	} else {
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 25e47c195874..83099a9a21d9 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -1976,8 +1976,12 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
>  		return -EACCES;
>  	}
>  
> -	if (arg_type == ARG_PTR_TO_MAP_KEY ||
> -	    arg_type == ARG_PTR_TO_MAP_VALUE) {
> +	if (arg_type == ARG_PTR_TO_MAP_KEY) {
> +		expected_type = PTR_TO_STACK;
> +		if (!type_is_pkt_pointer(type) && type != PTR_TO_MAP_VALUE &&
> +		    type != expected_type && type != SCALAR_VALUE)
> +			goto err_type;
> +	} else if (arg_type == ARG_PTR_TO_MAP_VALUE) {
>  		expected_type = PTR_TO_STACK;
>  		if (!type_is_pkt_pointer(type) && type != PTR_TO_MAP_VALUE &&
>  		    type != expected_type)
> @@ -2021,6 +2025,7 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
>  		/* bpf_map_xxx(map_ptr) call: remember that map_ptr */
>  		meta->map_ptr = reg->map_ptr;
>  	} else if (arg_type == ARG_PTR_TO_MAP_KEY) {
> +		bool zero_size_allowed = false;
>  		/* bpf_map_xxx(..., map_ptr, ..., key) call:
>  		 * check that [key, key + map->key_size) are within
>  		 * stack limits and initialized
> @@ -2034,8 +2039,13 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
>  			verbose(env, "invalid map_ptr to access map->key\n");
>  			return -EACCES;
>  		}
> +
> +		if (meta->map_ptr->map_type == BPF_MAP_TYPE_QUEUE)

Here as well.

> +			zero_size_allowed = true;

Also, verifier should rather enforce a const NULL key here than allowing one to
be set (but not as the only 'valid' input option), meaning, I don't think it would
be good to allow a 'zero' sized pointer to stack in this case.

>  		err = check_helper_mem_access(env, regno,
> -					      meta->map_ptr->key_size, false,
> +					      meta->map_ptr->key_size,
> +					      zero_size_allowed,
>  					      NULL);
>  	} else if (arg_type == ARG_PTR_TO_MAP_VALUE) {
>  		/* bpf_map_xxx(..., map_ptr, ..., value) call:
> 

^ permalink raw reply

* Re: [PATCH bpf-next 2/3] selftests/bpf: add test cases for BPF_MAP_TYPE_QUEUE
From: Daniel Borkmann @ 2018-08-07 13:42 UTC (permalink / raw)
  To: Mauricio Vasquez B, Alexei Starovoitov; +Cc: netdev
In-Reply-To: <153356391611.6981.14864460244240605372.stgit@kernel>

On 08/06/2018 03:58 PM, Mauricio Vasquez B wrote:
> Signed-off-by: Mauricio Vasquez B <mauricio.vasquez@polito.it>
> ---
>  tools/include/uapi/linux/bpf.h          |    5 ++
>  tools/testing/selftests/bpf/test_maps.c |   72 +++++++++++++++++++++++++++++++
>  2 files changed, 77 insertions(+)
> 
> diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
> index 0ebaaf7f3568..2c171c40eb45 100644
> --- a/tools/include/uapi/linux/bpf.h
> +++ b/tools/include/uapi/linux/bpf.h
> @@ -120,6 +120,7 @@ enum bpf_map_type {
>  	BPF_MAP_TYPE_CPUMAP,
>  	BPF_MAP_TYPE_XSKMAP,
>  	BPF_MAP_TYPE_SOCKHASH,
> +	BPF_MAP_TYPE_QUEUE,
>  };
>  
>  enum bpf_prog_type {
> @@ -255,6 +256,10 @@ enum bpf_attach_type {
>  /* Flag for stack_map, store build_id+offset instead of pointer */
>  #define BPF_F_STACK_BUILD_ID	(1U << 5)
>  
> +/* Flags for queue_map, type of queue */
> +#define BPF_F_QUEUE_FIFO	(1U << 16)
> +#define BPF_F_QUEUE_LIFO	(2U << 16)
> +
>  enum bpf_stack_build_id_status {
>  	/* user space need an empty entry to identify end of a trace */
>  	BPF_STACK_BUILD_ID_EMPTY = 0,
> diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
> index 6c253343a6f9..34567b017dbb 100644
> --- a/tools/testing/selftests/bpf/test_maps.c
> +++ b/tools/testing/selftests/bpf/test_maps.c
> @@ -457,6 +457,77 @@ static void test_devmap(int task, void *data)
>  	close(fd);
>  }
>  
> +static void test_queuemap(int task, void *data)
> +{
> +	__u32 value;
> +	int fd, i;
> +
> +	/* test FIFO */
> +	fd = bpf_create_map(BPF_MAP_TYPE_QUEUE, 0, sizeof(value), 32,
> +			    BPF_F_QUEUE_FIFO);

We should also feed in 'map_flags' so that both prealloc and non-prealloc
will be tested.

> +	if (fd < 0) {
> +		printf("Failed to create queuemap '%s'!\n", strerror(errno));
> +		exit(1);
> +	}
> +
> +	/* Push 32 elements */
> +	for (i = 0; i < 32; i++) {
> +		value = 1000 - i * 3;
> +		assert(bpf_map_update_elem(fd, NULL, &value, 0) == 0);
> +	}
> +
> +	/* Check that element cannot be pushed due to max_entries limit */
> +	value = 1000;
> +	assert(bpf_map_update_elem(fd, NULL, &value, 0) == -1 &&
> +	       errno == E2BIG);
> +
> +	/* Pop all elements */
> +	for (i = 0; i < 32; i++)
> +		assert(bpf_map_lookup_elem(fd, NULL, &value) == 0 &&
> +		       value == (1000 - i * 3));
> +
> +	/* Check that there are not elements left */
> +	assert(bpf_map_lookup_elem(fd, NULL, &value) == -1 && errno == ENOENT);
> +
> +	assert(bpf_map_delete_elem(fd, NULL) == -1 && errno == EINVAL);
> +	assert(bpf_map_get_next_key(fd, NULL, NULL) == -1 && errno == EINVAL);
> +
> +	close(fd);
> +
> +	/* test LIFO */
> +	fd = bpf_create_map(BPF_MAP_TYPE_QUEUE, 0, sizeof(value), 32,
> +			    BPF_F_QUEUE_LIFO);

Ditto.

> +	if (fd < 0) {
> +		printf("Failed to create queuemap '%s'!\n", strerror(errno));
> +		exit(1);
> +	}
> +
> +	/* Push 32 elements */
> +	for (i = 0; i < 32; i++) {
> +		value = 1000 - i * 3;
> +		assert(bpf_map_update_elem(fd, NULL, &value, 0) == 0);
> +	}
> +
> +	/* Check that element cannot be pushed due to max_entries limit */
> +	value = 1000;
> +	assert(bpf_map_update_elem(fd, NULL, &value, 0) == -1 &&
> +	       errno == E2BIG);
> +
> +	/* Pop all elements */
> +	for (i = 31; i >= 0; i--)
> +		assert(bpf_map_lookup_elem(fd, NULL, &value) == 0 &&
> +		       value == (1000 - i * 3));
> +
> +	/* Check that there are not elements left */
> +	assert(bpf_map_lookup_elem(fd, NULL, &value) == -1 &&
> +	       errno == ENOENT);
> +
> +	assert(bpf_map_delete_elem(fd, NULL) == -1 && errno == EINVAL);
> +	assert(bpf_map_get_next_key(fd, NULL, NULL) == -1 && errno == EINVAL);
> +
> +	close(fd);
> +}
> +
>  #include <sys/socket.h>
>  #include <sys/ioctl.h>
>  #include <arpa/inet.h>
> @@ -1162,6 +1233,7 @@ static void run_all_tests(void)
>  	test_arraymap_percpu_many_keys();
>  
>  	test_devmap(0, NULL);
> +	test_queuemap(0, NULL);
>  	test_sockmap(0, NULL);
>  
>  	test_map_large();
> 

^ permalink raw reply

* Re: [PATCH bpf-next 3/3] bpf: add sample for BPF_MAP_TYPE_QUEUE
From: Daniel Borkmann @ 2018-08-07 13:44 UTC (permalink / raw)
  To: Mauricio Vasquez B, Alexei Starovoitov; +Cc: netdev
In-Reply-To: <153356392410.6981.1290059578982921349.stgit@kernel>

On 08/06/2018 03:58 PM, Mauricio Vasquez B wrote:
> The example is made by two parts, a eBPF program that consumes elements
> from a FIFO queue and prints them in the screen and a user space
> application that inserts new elements into the queue each time this is
> executed.
> 
> Signed-off-by: Mauricio Vasquez B <mauricio.vasquez@polito.it>
> ---
>  samples/bpf/.gitignore             |    1 +
>  samples/bpf/Makefile               |    3 ++
>  samples/bpf/test_map_in_map_user.c |    9 +-----
>  samples/bpf/test_queuemap.sh       |   37 +++++++++++++++++++++++++
>  samples/bpf/test_queuemap_kern.c   |   51 +++++++++++++++++++++++++++++++++++
>  samples/bpf/test_queuemap_user.c   |   53 ++++++++++++++++++++++++++++++++++++
>  6 files changed, 147 insertions(+), 7 deletions(-)
>  create mode 100755 samples/bpf/test_queuemap.sh
>  create mode 100644 samples/bpf/test_queuemap_kern.c
>  create mode 100644 samples/bpf/test_queuemap_user.c
> 
> diff --git a/samples/bpf/.gitignore b/samples/bpf/.gitignore
> index 8ae4940025f8..d7e518c1b3ed 100644
> --- a/samples/bpf/.gitignore
> +++ b/samples/bpf/.gitignore
> @@ -26,6 +26,7 @@ test_lru_dist
>  test_map_in_map
>  test_overhead
>  test_probe_write_user
> +test_queuemap
>  trace_event
>  trace_output
>  tracex1
> diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
> index f88d5683d6ee..624f4f4b81db 100644
> --- a/samples/bpf/Makefile
> +++ b/samples/bpf/Makefile
> @@ -53,6 +53,7 @@ hostprogs-y += xdpsock
>  hostprogs-y += xdp_fwd
>  hostprogs-y += task_fd_query
>  hostprogs-y += xdp_sample_pkts
> +hostprogs-y += test_queuemap
>  
>  # Libbpf dependencies
>  LIBBPF = $(TOOLS_PATH)/lib/bpf/libbpf.a
> @@ -109,6 +110,7 @@ xdpsock-objs := xdpsock_user.o
>  xdp_fwd-objs := xdp_fwd_user.o
>  task_fd_query-objs := bpf_load.o task_fd_query_user.o $(TRACE_HELPERS)
>  xdp_sample_pkts-objs := xdp_sample_pkts_user.o $(TRACE_HELPERS)
> +test_queuemap-objs := bpf_load.o test_queuemap_user.o
>  
>  # Tell kbuild to always build the programs
>  always := $(hostprogs-y)
> @@ -166,6 +168,7 @@ always += xdpsock_kern.o
>  always += xdp_fwd_kern.o
>  always += task_fd_query_kern.o
>  always += xdp_sample_pkts_kern.o
> +always += test_queuemap_kern.o
>  
>  HOSTCFLAGS += -I$(objtree)/usr/include
>  HOSTCFLAGS += -I$(srctree)/tools/lib/
> diff --git a/samples/bpf/test_map_in_map_user.c b/samples/bpf/test_map_in_map_user.c
> index e308858f7bcf..28edac94234e 100644
> --- a/samples/bpf/test_map_in_map_user.c
> +++ b/samples/bpf/test_map_in_map_user.c
> @@ -1,10 +1,5 @@
> -/*
> - * Copyright (c) 2017 Facebook
> - *
> - * This program is free software; you can redistribute it and/or
> - * modify it under the terms of version 2 of the GNU General Public
> - * License as published by the Free Software Foundation.
> - */
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2018 Politecnico di Torino */

I don't think you can remove above Copyright and replace it with a different one. ;)

>  #include <sys/resource.h>
>  #include <sys/socket.h>
>  #include <arpa/inet.h>
> diff --git a/samples/bpf/test_queuemap.sh b/samples/bpf/test_queuemap.sh
> new file mode 100755
> index 000000000000..ed08c1fa8c2c
> --- /dev/null
> +++ b/samples/bpf/test_queuemap.sh
> @@ -0,0 +1,37 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +
> +[[ -z $TC ]] && TC='tc'
> +[[ -z $IP ]] && IP='ip'
> +
> +TEST_QUEUE_USER='./test_queuemap'
> +TEST_QUEUE_BPF='./test_queuemap_kern.o'
> +
> +function config {
> +	$IP netns add ns1
> +	$IP link add ve1 type veth peer name vens1
> +	$IP link set dev ve1 up
> +	$IP link set dev ve1 mtu 1500
> +	$IP link set dev vens1 netns ns1
> +
> +	$IP -n ns1 link set dev lo up
> +	$IP -n ns1 link set dev vens1 up
> +	$IP -n ns1 addr add 10.1.1.101/24 dev vens1
> +
> +	$IP addr add 10.1.1.1/24 dev ve1
> +	$TC qdisc add dev ve1 clsact
> +	$TC filter add dev ve1 ingress bpf da obj $TEST_QUEUE_BPF sec test_queue
> +}
> +
> +function cleanup {
> +	set +e
> +	[[ -z $DEBUG ]] || set +x
> +	$IP netns delete ns1 >& /dev/null
> +	$IP link del ve1 >& /dev/null
> +	rm -f /sys/fs/bpf/tc/globals/queue
> +	[[ -z $DEBUG ]] || set -x
> +	set -e
> +}
> +
> +cleanup
> +config
> diff --git a/samples/bpf/test_queuemap_kern.c b/samples/bpf/test_queuemap_kern.c
> new file mode 100644
> index 000000000000..2b496dafaffd
> --- /dev/null
> +++ b/samples/bpf/test_queuemap_kern.c
> @@ -0,0 +1,51 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2018 Politecnico di Torino */
> +#define KBUILD_MODNAME "foo"
> +#include <linux/ptrace.h>
> +#include <linux/version.h>
> +#include <uapi/linux/bpf.h>
> +#include <uapi/linux/in6.h>
> +#include <uapi/linux/pkt_cls.h>
> +#include "bpf_helpers.h"
> +
> +#define PIN_GLOBAL_NS		2
> +
> +struct bpf_elf_map {
> +	__u32 type;
> +	__u32 key_size;
> +	__u32 value_size;
> +	__u32 max_entries;
> +	__u32 flags;
> +	__u32 id;
> +	__u32 pinning;
> +};
> +
> +/* map #0 */
> +struct bpf_elf_map SEC("maps") queue = {
> +	.type = BPF_MAP_TYPE_QUEUE,
> +	.key_size = 0,
> +	.value_size = sizeof(u32),
> +	.flags = BPF_F_QUEUE_FIFO,
> +	.max_entries = 1024,
> +	.pinning = PIN_GLOBAL_NS,
> +};
> +
> +SEC("test_queue")
> +int _test_queue(struct __sk_buff *skb)
> +{
> +	char msg[] = "element is %u\n";
> +	char msg_no[] = "there are not elements\n";
> +
> +	u32 *val = bpf_map_lookup_elem(&queue, NULL);
> +
> +	if (!val) {
> +		bpf_trace_printk(msg_no, sizeof(msg_no));
> +		return TC_ACT_OK;
> +	}
> +
> +	bpf_trace_printk(msg, sizeof(msg), *val);

Could we add a more elaborate example? In cover letter and patch 1 which
implements the map, you mention SNAT, perhaps it would be useful to make
it a minimal sample app.

> +	return TC_ACT_OK;
> +}
> +
> +char _license[] SEC("license") = "GPL";
> +u32 _version SEC("version") = LINUX_VERSION_CODE;
> diff --git a/samples/bpf/test_queuemap_user.c b/samples/bpf/test_queuemap_user.c
> new file mode 100644
> index 000000000000..68f9a5d54596
> --- /dev/null
> +++ b/samples/bpf/test_queuemap_user.c
> @@ -0,0 +1,53 @@
> +/*
> + * Copyright (c) 2018 Politecnico di Torino
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of version 2 of the GNU General Public
> + * License as published by the Free Software Foundation.
> + */
> +#include <sys/resource.h>
> +#include <sys/socket.h>
> +#include <arpa/inet.h>
> +#include <stdint.h>
> +#include <assert.h>
> +#include <errno.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <bpf/bpf.h>
> +#include "bpf_load.h"
> +
> +int queue_map;
> +
> +static void test_queue_map(void)
> +{
> +	int ret;
> +	uint32_t i;
> +
> +	queue_map = bpf_obj_get("/sys/fs/bpf/tc/globals/queue");
> +	if (queue_map < 0) {
> +		fprintf(stderr, "error getting map");
> +		return;
> +	}
> +
> +	for (i = 0; i < 256; i++) {
> +		uint32_t v = 1000 - i*3;
> +
> +		ret = bpf_map_update_elem(queue_map, NULL, &v, 0);
> +		if (ret)
> +			fprintf(stderr, "ret is %d\n", ret);
> +	}
> +}
> +
> +int main(int argc, char **argv)
> +{
> +	struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
> +	char filename[256];
> +
> +	assert(!setrlimit(RLIMIT_MEMLOCK, &r));
> +
> +	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
> +
> +	test_queue_map();
> +
> +	return 0;
> +}
> 

^ permalink raw reply

* for editing
From: Roy Robinson @ 2018-08-07 10:51 UTC (permalink / raw)
  To: netdev

Did you receive my email yesterday?

Just want to check if you have needs for photo editing for our studio?
We normally edit 300 images within 12-24 hours.

We take care of different kinds of e-commerce photos, jewelry images, and
portrait model images.

Including cutting out and clipping path and others, we also give retouching
for your images.

You may drop us a photo if you want to check our quality, we will provide
testing.

Thanks,
Roy

^ permalink raw reply

* Re: [PATCH bpf-next 1/3] bpf: add bpf queue map
From: Daniel Borkmann @ 2018-08-07 13:52 UTC (permalink / raw)
  To: Mauricio Vasquez B, Alexei Starovoitov; +Cc: netdev
In-Reply-To: <153356390770.6981.4228793745105954649.stgit@kernel>

On 08/06/2018 03:58 PM, Mauricio Vasquez B wrote:
> Bpf queue implements a LIFO/FIFO data containers for ebpf programs.
> 
> It allows to push an element to the queue by using the update operation
> and to pop an element from the queue by using the lookup operation.
> 
> A use case for this is to keep track of a pool of elements, like
> network ports in a SNAT.
> 
> Signed-off-by: Mauricio Vasquez B <mauricio.vasquez@polito.it>
[...]
> +static int prealloc_init(struct bpf_queue *queue)
> +{
> +	u32 node_size = sizeof(struct queue_node) +
> +			round_up(queue->map.value_size, 8);
> +	u32 num_entries = queue->map.max_entries;
> +	int err;
> +
> +	queue->nodes = bpf_map_area_alloc(node_size * num_entries,
> +					  queue->map.numa_node);

That doesn't work either. If you don't set numa node, then here in
your case you'll always use numa node 0, which is unintentional.
You need to get the node via bpf_map_attr_numa_node(attr) helper.
Same issue in queue_map_update_elem().

^ permalink raw reply

* Re: [net-next:master 1745/1753] drivers/net/ieee802154/mac802154_hwsim.c:39:14: sparse: incorrect type in initializer (different address spaces)
From: Alexander Aring @ 2018-08-07 13:54 UTC (permalink / raw)
  To: netdev; +Cc: Stefan Schmidt
In-Reply-To: <201808070717.QVq6ok1n%fengguang.wu@intel.com>

Hi,

On Tue, Aug 07, 2018 at 07:07:20AM +0800, kbuild test robot wrote:
> tree:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git master
> head:   de7de576eca204de9a38e2f6dafe6b7c1ddc85c1
> commit: f25da51fdc381ca2863248c7060b3662632f0872 [1745/1753] ieee802154: hwsim: add replacement for fakelb
> reproduce:
>         # apt-get install sparse
>         git checkout f25da51fdc381ca2863248c7060b3662632f0872
>         make ARCH=x86_64 allmodconfig
>         make C=1 CF=-D__CHECK_ENDIAN__
> 
> 
> sparse warnings: (new ones prefixed by >>)
> 

oops sorry, I will take care of those immediately.

- Alex

^ permalink raw reply

* Re: [PATCH v8 bpf-next 02/10] veth: Add driver XDP
From: Daniel Borkmann @ 2018-08-07 14:26 UTC (permalink / raw)
  To: Toshiaki Makita, Alexei Starovoitov
  Cc: netdev, Jesper Dangaard Brouer, Jakub Kicinski, John Fastabend
In-Reply-To: <1533283098-2397-3-git-send-email-makita.toshiaki@lab.ntt.co.jp>

On 08/03/2018 09:58 AM, Toshiaki Makita wrote:
> This is the basic implementation of veth driver XDP.
> 
> Incoming packets are sent from the peer veth device in the form of skb,
> so this is generally doing the same thing as generic XDP.
> 
> This itself is not so useful, but a starting point to implement other
> useful veth XDP features like TX and REDIRECT.
> 
> This introduces NAPI when XDP is enabled, because XDP is now heavily
> relies on NAPI context. Use ptr_ring to emulate NIC ring. Tx function
> enqueues packets to the ring and peer NAPI handler drains the ring.
> 
> Currently only one ring is allocated for each veth device, so it does
> not scale on multiqueue env. This can be resolved by allocating rings
> on the per-queue basis later.
> 
> Note that NAPI is not used but netif_rx is used when XDP is not loaded,
> so this does not change the default behaviour.
> 
> v6:
> - Check skb->len only when allocation is needed.
> - Add __GFP_NOWARN to alloc_page() as it can be triggered by external
>   events.
> 
> v3:
> - Fix race on closing the device.
> - Add extack messages in ndo_bpf.
> 
> v2:
> - Squashed with the patch adding NAPI.
> - Implement adjust_tail.
> - Don't acquire consumer lock because it is guarded by NAPI.
> - Make poll_controller noop since it is unnecessary.
> - Register rxq_info on enabling XDP rather than on opening the device.
> 
> Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
[...]
> +
> +static struct sk_buff *veth_xdp_rcv_skb(struct veth_priv *priv,
> +					struct sk_buff *skb)
> +{
> +	u32 pktlen, headroom, act, metalen;
> +	void *orig_data, *orig_data_end;
> +	struct bpf_prog *xdp_prog;
> +	int mac_len, delta, off;
> +	struct xdp_buff xdp;
> +
> +	rcu_read_lock();
> +	xdp_prog = rcu_dereference(priv->xdp_prog);
> +	if (unlikely(!xdp_prog)) {
> +		rcu_read_unlock();
> +		goto out;
> +	}
> +
> +	mac_len = skb->data - skb_mac_header(skb);
> +	pktlen = skb->len + mac_len;
> +	headroom = skb_headroom(skb) - mac_len;
> +
> +	if (skb_shared(skb) || skb_head_is_locked(skb) ||
> +	    skb_is_nonlinear(skb) || headroom < XDP_PACKET_HEADROOM) {

Hmm, I think this is not fully correct. What happens if you have cloned skbs as
e.g. the case with TCP? This would also need a full expensive unclone to make the
data private as expected by XDP (this is basically a similar issue in generic
XDP). It may potentially be worth to also share the code here with generic XDP
implementation given it's quite similar?

> +		struct sk_buff *nskb;
> +		int size, head_off;
> +		void *head, *start;
> +		struct page *page;
> +
> +		size = SKB_DATA_ALIGN(VETH_XDP_HEADROOM + pktlen) +
> +		       SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
> +		if (size > PAGE_SIZE)
> +			goto drop;
> +
> +		page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
> +		if (!page)
> +			goto drop;
> +
> +		head = page_address(page);
> +		start = head + VETH_XDP_HEADROOM;
> +		if (skb_copy_bits(skb, -mac_len, start, pktlen)) {
> +			page_frag_free(head);
> +			goto drop;
> +		}
> +
> +		nskb = veth_build_skb(head,
> +				      VETH_XDP_HEADROOM + mac_len, skb->len,
> +				      PAGE_SIZE);
> +		if (!nskb) {
> +			page_frag_free(head);
> +			goto drop;
> +		}
> +
> +		skb_copy_header(nskb, skb);
> +		head_off = skb_headroom(nskb) - skb_headroom(skb);
> +		skb_headers_offset_update(nskb, head_off);
> +		if (skb->sk)
> +			skb_set_owner_w(nskb, skb->sk);
> +		consume_skb(skb);
> +		skb = nskb;
> +	}
> +
> +	xdp.data_hard_start = skb->head;
> +	xdp.data = skb_mac_header(skb);
> +	xdp.data_end = xdp.data + pktlen;
> +	xdp.data_meta = xdp.data;
> +	xdp.rxq = &priv->xdp_rxq;
> +	orig_data = xdp.data;
> +	orig_data_end = xdp.data_end;
> +
> +	act = bpf_prog_run_xdp(xdp_prog, &xdp);
> +
> +	switch (act) {
> +	case XDP_PASS:
> +		break;
> +	default:
> +		bpf_warn_invalid_xdp_action(act);
> +	case XDP_ABORTED:
> +		trace_xdp_exception(priv->dev, xdp_prog, act);
> +	case XDP_DROP:
> +		goto drop;
> +	}
> +	rcu_read_unlock();
> +
> +	delta = orig_data - xdp.data;
> +	off = mac_len + delta;
> +	if (off > 0)
> +		__skb_push(skb, off);
> +	else if (off < 0)
> +		__skb_pull(skb, -off);
> +	skb->mac_header -= delta;
> +	off = xdp.data_end - orig_data_end;
> +	if (off != 0)
> +		__skb_put(skb, off);
> +	skb->protocol = eth_type_trans(skb, priv->dev);
> +
> +	metalen = xdp.data - xdp.data_meta;
> +	if (metalen)
> +		skb_metadata_set(skb, metalen);
> +out:
> +	return skb;
> +drop:
> +	rcu_read_unlock();
> +	kfree_skb(skb);
> +	return NULL;
> +}

^ permalink raw reply

* [PATCH net-next] ieee802154: hwsim: fix rcu address annotation
From: Alexander Aring @ 2018-08-07 14:34 UTC (permalink / raw)
  To: netdev; +Cc: linux-wpan, kernel, Alexander Aring, Stefan Schmidt

This patch fixes the following sparse warning about mismatch rcu
attribute for address space annotation:

...
error: incompatible types in comparison expression (different modifiers)
error: incompatible types in comparison expression (different address spaces)
...

Some __rcu annotation was at non-pointers list head structures and one was
missing in edge information which is used by rcu_assign_pointer() to
update edge setting information.

Cc: Stefan Schmidt <stefan@datenfreihafen.org>
Fixes: f25da51fdc38 ("ieee802154: hwsim: add replacement for fakelb")
Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
Hopefully I did it right now. Sorry again.

 drivers/net/ieee802154/mac802154_hwsim.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c
index 1982308b9b1c..f4e92054f7df 100644
--- a/drivers/net/ieee802154/mac802154_hwsim.c
+++ b/drivers/net/ieee802154/mac802154_hwsim.c
@@ -36,7 +36,7 @@ MODULE_LICENSE("GPL");
 static LIST_HEAD(hwsim_phys);
 static DEFINE_MUTEX(hwsim_phys_lock);
 
-static __rcu LIST_HEAD(hwsim_ifup_phys);
+static LIST_HEAD(hwsim_ifup_phys);
 
 static struct platform_device *mac802154hwsim_dev;
 
@@ -68,7 +68,7 @@ struct hwsim_edge_info {
 
 struct hwsim_edge {
 	struct hwsim_phy *endpoint;
-	struct hwsim_edge_info *info;
+	struct hwsim_edge_info __rcu *info;
 
 	struct list_head list;
 	struct rcu_head rcu;
@@ -81,7 +81,7 @@ struct hwsim_phy {
 	struct hwsim_pib __rcu *pib;
 
 	bool suspended;
-	struct list_head __rcu edges;
+	struct list_head edges;
 
 	struct list_head list;
 	struct list_head list_ifup;
-- 
2.11.0

^ permalink raw reply related

* Re: [PATCH bpf-next 1/3] bpf: add bpf queue map
From: Alexei Starovoitov @ 2018-08-07 14:42 UTC (permalink / raw)
  To: Mauricio Vasquez B; +Cc: Alexei Starovoitov, Daniel Borkmann, netdev
In-Reply-To: <153356390770.6981.4228793745105954649.stgit@kernel>

On Mon, Aug 06, 2018 at 03:58:30PM +0200, Mauricio Vasquez B wrote:
> Bpf queue implements a LIFO/FIFO data containers for ebpf programs.

queue/stack datastructure would be a great addition.

> It allows to push an element to the queue by using the update operation
> and to pop an element from the queue by using the lookup operation.
> 
> A use case for this is to keep track of a pool of elements, like
> network ports in a SNAT.
> 
> Signed-off-by: Mauricio Vasquez B <mauricio.vasquez@polito.it>
> ---
>  include/linux/bpf_types.h |    1 
>  include/uapi/linux/bpf.h  |    5 +
>  kernel/bpf/Makefile       |    2 
>  kernel/bpf/queuemap.c     |  287 +++++++++++++++++++++++++++++++++++++++++++++
>  kernel/bpf/syscall.c      |   61 +++++++---
>  kernel/bpf/verifier.c     |   16 ++-
>  6 files changed, 353 insertions(+), 19 deletions(-)
>  create mode 100644 kernel/bpf/queuemap.c
> 
> diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h
> index c5700c2d5549..6c7a62f3fe43 100644
> --- a/include/linux/bpf_types.h
> +++ b/include/linux/bpf_types.h
> @@ -58,3 +58,4 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_CPUMAP, cpu_map_ops)
>  BPF_MAP_TYPE(BPF_MAP_TYPE_XSKMAP, xsk_map_ops)
>  #endif
>  #endif
> +BPF_MAP_TYPE(BPF_MAP_TYPE_QUEUE, queue_map_ops)
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index 0ebaaf7f3568..2c171c40eb45 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -120,6 +120,7 @@ enum bpf_map_type {
>  	BPF_MAP_TYPE_CPUMAP,
>  	BPF_MAP_TYPE_XSKMAP,
>  	BPF_MAP_TYPE_SOCKHASH,
> +	BPF_MAP_TYPE_QUEUE,
>  };
>  
>  enum bpf_prog_type {
> @@ -255,6 +256,10 @@ enum bpf_attach_type {
>  /* Flag for stack_map, store build_id+offset instead of pointer */
>  #define BPF_F_STACK_BUILD_ID	(1U << 5)
>  
> +/* Flags for queue_map, type of queue */
> +#define BPF_F_QUEUE_FIFO	(1U << 16)
> +#define BPF_F_QUEUE_LIFO	(2U << 16)

the choice of flags looks odd.
Why start at bit 16 and why waste two bits?
It's either stack or queue.
May be instead define two map_types:
BPF_MAP_TYPE_QUEUE and BPF_MAP_TYPE_STACK
that share common implementation?

And how about adding three new helpers: push/pop/peek as well?
Reusing lookup/update is neat, but does lookup == pop
or does lookup == peek ?
I suspect it will be confusing.
Three new helpers cost nothing, but will make bpf progs easier to read.

Could you also add a flag for replacement policy?
In this implementation when max_entries limit is reached
the map_update_elem (aka push) will fail with e2big.
It would be useful to allow pushing and dropping elements from
the other side then such queue/stack can be used to keep
track of the last N events (the prog would unconditionally push
and user space would swap the queue for new one via map-in-map
and drain old queue).
Speaking of map-in-map, please add a test to make sure
queue/stack works with hash/array_of_maps.

selftests in patch2 needs to have kernel side as well.
it's not enough to test syscall access only.

^ permalink raw reply

* [PATCH 0/3] Add Broadcom Omega SoC internal switch and phy
From: Arun Parameswaran @ 2018-08-07 17:02 UTC (permalink / raw)
  To: David S. Miller, Florian Fainelli, Andrew Lunn, Vivien Didelot,
	Rob Herring, Mark Rutland
  Cc: netdev, devicetree, linux-kernel, bcm-kernel-feedback-list,
	Arun Parameswaran

Hi,

The patchset is based on David Miller's "net-next" repo.

The patches add support for the Broadcom Omega SoC's internal ethernet
switch and the internal gphy.

The internal ethernet switch in the Omega is a b53 srab based switch.
The support for the switch is added to the b53 driver in the dsa
framework.

The gphy support is added to the bcm7xxx driver.

Thanks
Arun

Arun Parameswaran (3):
  dt-bindings: net: dsa: Add compatibility strings for Broadcom Omega
  net: dsa: b53: Add support for Broadcom Omega SoC internal switch
  net: phy: Add support for Broadcom Omega internal Combo GPHY

 Documentation/devicetree/bindings/net/dsa/b53.txt | 8 ++++++++
 drivers/net/dsa/b53/b53_srab.c                    | 1 +
 drivers/net/phy/bcm7xxx.c                         | 2 ++
 include/linux/brcmphy.h                           | 1 +
 4 files changed, 12 insertions(+)

-- 
1.9.1

^ permalink raw reply

* [PATCH 1/3] dt-bindings: net: dsa: Add compatibility strings for Broadcom Omega
From: Arun Parameswaran @ 2018-08-07 17:02 UTC (permalink / raw)
  To: David S. Miller, Florian Fainelli, Andrew Lunn, Vivien Didelot,
	Rob Herring, Mark Rutland
  Cc: netdev, devicetree, linux-kernel, bcm-kernel-feedback-list,
	Arun Parameswaran
In-Reply-To: <1533661364-15381-1-git-send-email-arun.parameswaran@broadcom.com>

Add compatibility strings for the internal switch in the Broadcom
Omega SoC family (BCM5831X/BCM1140X) to B53.

Signed-off-by: Arun Parameswaran <arun.parameswaran@broadcom.com>
---
 Documentation/devicetree/bindings/net/dsa/b53.txt | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/dsa/b53.txt b/Documentation/devicetree/bindings/net/dsa/b53.txt
index 47a6a7f..1811e19 100644
--- a/Documentation/devicetree/bindings/net/dsa/b53.txt
+++ b/Documentation/devicetree/bindings/net/dsa/b53.txt
@@ -24,6 +24,14 @@ Required properties:
       "brcm,bcm53018-srab"
       "brcm,bcm53019-srab" and the mandatory "brcm,bcm5301x-srab" string
 
+  For the BCM5831X/BCM1140x SoCs with an integrated switch, must be one of:
+      "brcm,bcm11404-srab"
+      "brcm,bcm11407-srab"
+      "brcm,bcm11409-srab"
+      "brcm,bcm58310-srab"
+      "brcm,bcm58311-srab"
+      "brcm,bcm58313-srab" and the mandatory "brcm,omega-srab" string
+
   For the BCM585xx/586XX/88312 SoCs with an integrated switch, must be one of:
       "brcm,bcm58522-srab"
       "brcm,bcm58523-srab"
-- 
1.9.1

^ permalink raw reply related

* [PATCH 3/3] net: phy: Add support for Broadcom Omega internal Combo GPHY
From: Arun Parameswaran @ 2018-08-07 17:02 UTC (permalink / raw)
  To: David S. Miller, Florian Fainelli, Andrew Lunn, Vivien Didelot,
	Rob Herring, Mark Rutland
  Cc: netdev, devicetree, linux-kernel, bcm-kernel-feedback-list,
	Arun Parameswaran
In-Reply-To: <1533661364-15381-1-git-send-email-arun.parameswaran@broadcom.com>

Add support for the Broadcom Omega SoC internal Combo Ethernet
GPHY to the bcm7xxx phy driver.

Signed-off-by: Arun Parameswaran <arun.parameswaran@broadcom.com>
---
 drivers/net/phy/bcm7xxx.c | 2 ++
 include/linux/brcmphy.h   | 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c
index 01d2ff2f..b2b6307 100644
--- a/drivers/net/phy/bcm7xxx.c
+++ b/drivers/net/phy/bcm7xxx.c
@@ -229,6 +229,7 @@ static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
 	phy_read(phydev, MII_BMSR);
 
 	switch (rev) {
+	case 0xa0:
 	case 0xb0:
 		ret = bcm7xxx_28nm_b0_afe_config_init(phydev);
 		break;
@@ -659,6 +660,7 @@ static int bcm7xxx_28nm_probe(struct phy_device *phydev)
 	BCM7XXX_28NM_GPHY(PHY_ID_BCM7439, "Broadcom BCM7439"),
 	BCM7XXX_28NM_GPHY(PHY_ID_BCM7439_2, "Broadcom BCM7439 (2)"),
 	BCM7XXX_28NM_GPHY(PHY_ID_BCM7445, "Broadcom BCM7445"),
+	BCM7XXX_28NM_GPHY(PHY_ID_BCM_OMEGA, "Broadcom Omega Combo GPHY"),
 	BCM7XXX_40NM_EPHY(PHY_ID_BCM7346, "Broadcom BCM7346"),
 	BCM7XXX_40NM_EPHY(PHY_ID_BCM7362, "Broadcom BCM7362"),
 	BCM7XXX_40NM_EPHY(PHY_ID_BCM7425, "Broadcom BCM7425"),
diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h
index daa9234..949e9af 100644
--- a/include/linux/brcmphy.h
+++ b/include/linux/brcmphy.h
@@ -45,6 +45,7 @@
 #define PHY_ID_BCM7445			0x600d8510
 
 #define PHY_ID_BCM_CYGNUS		0xae025200
+#define PHY_ID_BCM_OMEGA		0xae025100
 
 #define PHY_BCM_OUI_MASK		0xfffffc00
 #define PHY_BCM_OUI_1			0x00206000
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH 1/3] net:svc_rdma_transport: remove unneeded variable 'ret' in rdma_listen_handler
From: Anna Schumaker @ 2018-08-07 14:49 UTC (permalink / raw)
  To: zhong jiang, davem, J. Bruce Fields; +Cc: netdev, linux-kernel
In-Reply-To: <1533640809-1221-2-git-send-email-zhongjiang@huawei.com>

(Adding Bruce since he takes nfs / sunrpc server patches)

On 08/07/2018 07:20 AM, zhong jiang wrote:
> The ret is not modified after initalization, So just remove the variable
> and return 0.
> 
> Signed-off-by: zhong jiang <zhongjiang@huawei.com>
> ---
>  net/sunrpc/xprtrdma/svc_rdma_transport.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
> index 547b2cd..2848caf 100644
> --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
> +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
> @@ -296,7 +296,6 @@ static int rdma_listen_handler(struct rdma_cm_id *cma_id,
>  			       struct rdma_cm_event *event)
>  {
>  	struct sockaddr *sap = (struct sockaddr *)&cma_id->route.addr.src_addr;
> -	int ret = 0;
>  
>  	trace_svcrdma_cm_event(event, sap);
>  
> @@ -315,7 +314,7 @@ static int rdma_listen_handler(struct rdma_cm_id *cma_id,
>  		break;
>  	}
>  
> -	return ret;
> +	return 0;
>  }
>  
>  static int rdma_cma_handler(struct rdma_cm_id *cma_id,
> 

^ permalink raw reply

* Re: [PATCH v4] can: sja1000: plx_pci: add support for ASEM CAN raw device
From: Flavio Suligoi @ 2018-08-07 14:50 UTC (permalink / raw)
  To: Marc Kleine-Budde, Wolfgang Grandegger
  Cc: David S . Miller, linux-can@vger.kernel.org,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <e5e06710-0304-0cf9-67fb-1e29f0678c86@pengutronix.de>

On 08/07/2018 04:11 PM, Marc Kleine-Budde wrote:

>On 08/07/2018 09:17 AM, Flavio Suligoi wrote:
>> This patch adds support for ASEM opto-isolated dual channels
>> CAN raw device (http://www.asem.it)
>>
>> Signed-off-by: Flavio Suligoi <f.suligoi@asem.it>
>> ---
>>
>> v2: - rename ASEM_... constants to reduce space size;
>>     - remove "else" in "plx_pci_reset_asem_dual_can_raw" function to avoid
>>       strings breaking
>> v3: - fix wrong comment for PLX_LINT2_POL
>>     - put string into just one line in "plx_pci_reset_asem_dual_can_raw"
>>       function
>> v4: - remove unnecessary variable "reset_bar" in
>>       "plx_pci_reset_asem_dual_can_raw" function
>>
>>  drivers/net/can/sja1000/Kconfig   |  1 +
>>  drivers/net/can/sja1000/plx_pci.c | 66 ++++++++++++++++++++++++++++++++++++++-
>>  2 files changed, 66 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig
>> index 1e65cb6..f6dc899 100644
>> --- a/drivers/net/can/sja1000/Kconfig
>> +++ b/drivers/net/can/sja1000/Kconfig
>> @@ -88,6 +88,7 @@ config CAN_PLX_PCI
>>          - TEWS TECHNOLOGIES TPMC810 card (http://www.tews.com/)
>>          - IXXAT Automation PC-I 04/PCI card (http://www.ixxat.com/)
>>          - Connect Tech Inc. CANpro/104-Plus Opto (CRG001) card (http://www.connecttech.com)
>> +        - ASEM CAN raw - 2 isolated CAN channels (www.asem.it)
>>
>>  config CAN_TSCAN1
>>       tristate "TS-CAN1 PC104 boards"
>> diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c
>> index f8ff25c..79fc327 100644
>> --- a/drivers/net/can/sja1000/plx_pci.c
>> +++ b/drivers/net/can/sja1000/plx_pci.c
>> @@ -46,7 +46,8 @@ MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, "
>>                       "esd CAN-PCIe/2000, "
>>                       "Connect Tech Inc. CANpro/104-Plus Opto (CRG001), "
>>                       "IXXAT PC-I 04/PCI, "
>> -                     "ELCUS CAN-200-PCI")
>> +                     "ELCUS CAN-200-PCI, "
>> +                     "ASEM DUAL CAN-RAW")
>>  MODULE_LICENSE("GPL v2");
>>
>>  #define PLX_PCI_MAX_CHAN 2
>> @@ -70,7 +71,9 @@ struct plx_pci_card {
>>                                        */
>>
>>  #define PLX_LINT1_EN 0x1             /* Local interrupt 1 enable */
>> +#define PLX_LINT1_POL        (1 << 1)        /* Local interrupt 1 polarity */
>>  #define PLX_LINT2_EN (1 << 3)        /* Local interrupt 2 enable */
>> +#define PLX_LINT2_POL        (1 << 4)        /* Local interrupt 2 polarity */
>>  #define PLX_PCI_INT_EN       (1 << 6)        /* PCI Interrupt Enable */
>>  #define PLX_PCI_RESET        (1 << 30)       /* PCI Adapter Software Reset */
>>
>> @@ -92,6 +95,9 @@ struct plx_pci_card {
>>   */
>>  #define PLX_PCI_OCR  (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL)
>>
>> +/* OCR setting for ASEM Dual CAN raw */
>> +#define ASEM_PCI_OCR 0xfe
>> +
>>  /*
>>   * In the CDR register, you should set CBP to 1.
>>   * You will probably also want to set the clock divider value to 7
>> @@ -145,10 +151,20 @@ struct plx_pci_card {
>>  #define MOXA_PCI_VENDOR_ID           0x1393
>>  #define MOXA_PCI_DEVICE_ID           0x0100
>>
>> +#define ASEM_RAW_CAN_VENDOR_ID               0x10b5
>> +#define ASEM_RAW_CAN_DEVICE_ID               0x9030
>> +#define ASEM_RAW_CAN_SUB_VENDOR_ID   0x3000
>> +#define ASEM_RAW_CAN_SUB_DEVICE_ID   0x1001
>> +#define ASEM_RAW_CAN_SUB_DEVICE_ID_BIS       0x1002
>> +#define ASEM_RAW_CAN_RST_REGISTER    0x54
>> +#define ASEM_RAW_CAN_RST_MASK_CAN1   0x20
>> +#define ASEM_RAW_CAN_RST_MASK_CAN2   0x04
>> +
>>  static void plx_pci_reset_common(struct pci_dev *pdev);
>>  static void plx9056_pci_reset_common(struct pci_dev *pdev);
>>  static void plx_pci_reset_marathon_pci(struct pci_dev *pdev);
>>  static void plx_pci_reset_marathon_pcie(struct pci_dev *pdev);
>> +static void plx_pci_reset_asem_dual_can_raw(struct pci_dev *pdev);
>>
>>  struct plx_pci_channel_map {
>>       u32 bar;
>> @@ -269,6 +285,14 @@ static struct plx_pci_card_info plx_pci_card_info_moxa = {
>>        /* based on PLX9052 */
>>  };
>>
>> +static struct plx_pci_card_info plx_pci_card_info_asem_dual_can = {
>> +     "ASEM Dual CAN raw PCI", 2,
>> +     PLX_PCI_CAN_CLOCK, ASEM_PCI_OCR, PLX_PCI_CDR,
>> +     {0, 0x00, 0x00}, { {2, 0x00, 0x00}, {4, 0x00, 0x00} },
>> +     &plx_pci_reset_asem_dual_can_raw
>> +     /* based on PLX9030 */
>> +};
>> +
>>  static const struct pci_device_id plx_pci_tbl[] = {
>>       {
>>               /* Adlink PCI-7841/cPCI-7841 */
>> @@ -375,6 +399,20 @@ static const struct pci_device_id plx_pci_tbl[] = {
>>               0, 0,
>>               (kernel_ulong_t)&plx_pci_card_info_moxa
>>       },
>> +     {
>> +             /* ASEM Dual CAN raw */
>> +             ASEM_RAW_CAN_VENDOR_ID, ASEM_RAW_CAN_DEVICE_ID,
>> +             ASEM_RAW_CAN_SUB_VENDOR_ID, ASEM_RAW_CAN_SUB_DEVICE_ID,
>> +             0, 0,
>> +             (kernel_ulong_t)&plx_pci_card_info_asem_dual_can
>> +     },
>> +     {
>> +             /* ASEM Dual CAN raw -new model */
>> +             ASEM_RAW_CAN_VENDOR_ID, ASEM_RAW_CAN_DEVICE_ID,
>> +             ASEM_RAW_CAN_SUB_VENDOR_ID, ASEM_RAW_CAN_SUB_DEVICE_ID_BIS,
>> +             0, 0,
>> +             (kernel_ulong_t)&plx_pci_card_info_asem_dual_can
>> +     },
>>       { 0,}
>>  };
>>  MODULE_DEVICE_TABLE(pci, plx_pci_tbl);
>> @@ -524,6 +562,32 @@ static void plx_pci_reset_marathon_pcie(struct pci_dev *pdev)
>>       }
>>  }
>>
>> +/* Special reset function for ASEM Dual CAN raw card */
>> +static void plx_pci_reset_asem_dual_can_raw(struct pci_dev *pdev)
>> +{
>> +     void __iomem *bar0_addr;
>> +     u8 tmpval;
>> +
>> +     plx_pci_reset_common(pdev);
>> +
>> +     bar0_addr = pci_iomap(pdev, 0, 0);
>> +     if (!bar0_addr) {
>> +             dev_err(&pdev->dev, "Failed to remap reset space %d (BAR%d)\n",
>> +                     0, 0);
>
>I've put both 0 directly into the string while applying the patch.
>
>Tnx,
>Marc

Thanks,
Flavio

>
>--
>Pengutronix e.K.                  | Marc Kleine-Budde           |
>Industrial Linux Solutions        | Phone: +49-231-2826-924     |
>Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
>Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

^ permalink raw reply

* Re: [PATCH 1/3] dt-bindings: net: dsa: Add compatibility strings for Broadcom Omega
From: Florian Fainelli @ 2018-08-07 17:06 UTC (permalink / raw)
  To: Arun Parameswaran, David S. Miller, Florian Fainelli, Andrew Lunn,
	Vivien Didelot, Rob Herring, Mark Rutland
  Cc: netdev, devicetree, linux-kernel, bcm-kernel-feedback-list
In-Reply-To: <1533661364-15381-2-git-send-email-arun.parameswaran@broadcom.com>

On 08/07/2018 10:02 AM, Arun Parameswaran wrote:
> Add compatibility strings for the internal switch in the Broadcom
> Omega SoC family (BCM5831X/BCM1140X) to B53.
> 
> Signed-off-by: Arun Parameswaran <arun.parameswaran@broadcom.com>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

^ 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