Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next 09/16] mlxsw: pci: PTP: Hook into packet transmit path
From: Ido Schimmel @ 2019-06-27 13:52 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, petrm, mlxsw, Ido Schimmel
In-Reply-To: <20190627135259.7292-1-idosch@idosch.org>

From: Petr Machata <petrm@mellanox.com>

On Spectrum-1, timestamps are delivered separately from the packets, and
need to paired up. Therefore, at some point after mlxsw_sp_port_xmit()
is invoked, it is necessary to involve the chip-specific driver code to
allow it to do the necessary bookkeeping and matching.

On Spectrum-2, timestamps are delivered in CQE. For that reason,
position the point of driver involvement into mlxsw_pci_cqe_sdq_handle()
to make it hopefully easier to extend for Spectrum-2 in the future.

To tell the driver what port the packet was sent on, keep tx_info
in SKB control buffer.

Introduce a new driver core interface mlxsw_core_ptp_transmitted(), a
driver callback ptp_transmitted, and a PTP op transmitted. The callee is
responsible for taking care of releasing the SKB passed to the new
interfaces, and correspondingly have the new stub callbacks just call
dev_kfree_skb_any().

Follow-up patches will introduce the actual content into
mlxsw_sp1_ptp_transmitted() in particular.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/core.c    |  9 +++++++++
 drivers/net/ethernet/mellanox/mlxsw/core.h    | 10 ++++++++++
 drivers/net/ethernet/mellanox/mlxsw/pci.c     | 17 ++++++++++++++++-
 .../net/ethernet/mellanox/mlxsw/spectrum.c    | 19 +++++++++++++++++++
 .../ethernet/mellanox/mlxsw/spectrum_ptp.c    |  6 ++++++
 .../ethernet/mellanox/mlxsw/spectrum_ptp.h    | 15 +++++++++++++++
 6 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index 30e0526a9cf6..17ceac7505e5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -1245,6 +1245,15 @@ int mlxsw_core_skb_transmit(struct mlxsw_core *mlxsw_core, struct sk_buff *skb,
 }
 EXPORT_SYMBOL(mlxsw_core_skb_transmit);
 
+void mlxsw_core_ptp_transmitted(struct mlxsw_core *mlxsw_core,
+				struct sk_buff *skb, u8 local_port)
+{
+	if (mlxsw_core->driver->ptp_transmitted)
+		mlxsw_core->driver->ptp_transmitted(mlxsw_core, skb,
+						    local_port);
+}
+EXPORT_SYMBOL(mlxsw_core_ptp_transmitted);
+
 static bool __is_rx_listener_equal(const struct mlxsw_rx_listener *rxl_a,
 				   const struct mlxsw_rx_listener *rxl_b)
 {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h
index 06babcc58c7a..8efcff4b59cb 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.h
@@ -48,6 +48,8 @@ bool mlxsw_core_skb_transmit_busy(struct mlxsw_core *mlxsw_core,
 				  const struct mlxsw_tx_info *tx_info);
 int mlxsw_core_skb_transmit(struct mlxsw_core *mlxsw_core, struct sk_buff *skb,
 			    const struct mlxsw_tx_info *tx_info);
+void mlxsw_core_ptp_transmitted(struct mlxsw_core *mlxsw_core,
+				struct sk_buff *skb, u8 local_port);
 
 struct mlxsw_rx_listener {
 	void (*func)(struct sk_buff *skb, u8 local_port, void *priv);
@@ -296,6 +298,13 @@ struct mlxsw_driver {
 			     u64 *p_linear_size);
 	int (*params_register)(struct mlxsw_core *mlxsw_core);
 	void (*params_unregister)(struct mlxsw_core *mlxsw_core);
+
+	/* Notify a driver that a timestamped packet was transmitted. Driver
+	 * is responsible for freeing the passed-in SKB.
+	 */
+	void (*ptp_transmitted)(struct mlxsw_core *mlxsw_core,
+				struct sk_buff *skb, u8 local_port);
+
 	u8 txhdr_len;
 	const struct mlxsw_config_profile *profile;
 	bool res_query_enabled;
@@ -419,6 +428,7 @@ enum mlxsw_devlink_param_id {
 };
 
 struct mlxsw_skb_cb {
+	struct mlxsw_tx_info tx_info;
 };
 
 static inline struct mlxsw_skb_cb *mlxsw_skb_cb(struct sk_buff *skb)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c
index 6acb9bbfdf89..051b19388a81 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/pci.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c
@@ -508,17 +508,28 @@ static void mlxsw_pci_cqe_sdq_handle(struct mlxsw_pci *mlxsw_pci,
 {
 	struct pci_dev *pdev = mlxsw_pci->pdev;
 	struct mlxsw_pci_queue_elem_info *elem_info;
+	struct mlxsw_tx_info tx_info;
 	char *wqe;
 	struct sk_buff *skb;
 	int i;
 
 	spin_lock(&q->lock);
 	elem_info = mlxsw_pci_queue_elem_info_consumer_get(q);
+	tx_info = mlxsw_skb_cb(elem_info->u.sdq.skb)->tx_info;
 	skb = elem_info->u.sdq.skb;
 	wqe = elem_info->elem;
 	for (i = 0; i < MLXSW_PCI_WQE_SG_ENTRIES; i++)
 		mlxsw_pci_wqe_frag_unmap(mlxsw_pci, wqe, i, DMA_TO_DEVICE);
-	dev_kfree_skb_any(skb);
+
+	if (unlikely(!tx_info.is_emad &&
+		     skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
+		mlxsw_core_ptp_transmitted(mlxsw_pci->core, skb,
+					   tx_info.local_port);
+		skb = NULL;
+	}
+
+	if (skb)
+		dev_kfree_skb_any(skb);
 	elem_info->u.sdq.skb = NULL;
 
 	if (q->consumer_counter++ != consumer_counter_limit)
@@ -1548,6 +1559,7 @@ static int mlxsw_pci_skb_transmit(void *bus_priv, struct sk_buff *skb,
 		err = -EAGAIN;
 		goto unlock;
 	}
+	mlxsw_skb_cb(skb)->tx_info = *tx_info;
 	elem_info->u.sdq.skb = skb;
 
 	wqe = elem_info->elem;
@@ -1571,6 +1583,9 @@ static int mlxsw_pci_skb_transmit(void *bus_priv, struct sk_buff *skb,
 			goto unmap_frags;
 	}
 
+	if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
+		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+
 	/* Set unused sq entries byte count to zero. */
 	for (i++; i < MLXSW_PCI_WQE_SG_ENTRIES; i++)
 		mlxsw_pci_wqe_byte_count_set(wqe, i, 0);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index a0376d4f94a8..6a907e491868 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -157,6 +157,12 @@ struct mlxsw_sp_ptp_ops {
 	 */
 	void (*receive)(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
 			u8 local_port);
+
+	/* Notify a driver that a timestamped packet was transmitted. Driver
+	 * is responsible for freeing the passed-in SKB.
+	 */
+	void (*transmitted)(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
+			    u8 local_port);
 };
 
 static int mlxsw_sp_component_query(struct mlxfw_dev *mlxfw_dev,
@@ -4424,12 +4430,14 @@ static const struct mlxsw_sp_ptp_ops mlxsw_sp1_ptp_ops = {
 	.clock_init	= mlxsw_sp1_ptp_clock_init,
 	.clock_fini	= mlxsw_sp1_ptp_clock_fini,
 	.receive	= mlxsw_sp1_ptp_receive,
+	.transmitted	= mlxsw_sp1_ptp_transmitted,
 };
 
 static const struct mlxsw_sp_ptp_ops mlxsw_sp2_ptp_ops = {
 	.clock_init	= mlxsw_sp2_ptp_clock_init,
 	.clock_fini	= mlxsw_sp2_ptp_clock_fini,
 	.receive	= mlxsw_sp2_ptp_receive,
+	.transmitted	= mlxsw_sp2_ptp_transmitted,
 };
 
 static int mlxsw_sp_netdevice_event(struct notifier_block *unused,
@@ -4995,6 +5003,15 @@ static void mlxsw_sp2_params_unregister(struct mlxsw_core *mlxsw_core)
 	mlxsw_sp_params_unregister(mlxsw_core);
 }
 
+static void mlxsw_sp_ptp_transmitted(struct mlxsw_core *mlxsw_core,
+				     struct sk_buff *skb, u8 local_port)
+{
+	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+
+	skb_pull(skb, MLXSW_TXHDR_LEN);
+	mlxsw_sp->ptp_ops->transmitted(mlxsw_sp, skb, local_port);
+}
+
 static struct mlxsw_driver mlxsw_sp1_driver = {
 	.kind				= mlxsw_sp1_driver_name,
 	.priv_size			= sizeof(struct mlxsw_sp),
@@ -5019,6 +5036,7 @@ static struct mlxsw_driver mlxsw_sp1_driver = {
 	.kvd_sizes_get			= mlxsw_sp_kvd_sizes_get,
 	.params_register		= mlxsw_sp_params_register,
 	.params_unregister		= mlxsw_sp_params_unregister,
+	.ptp_transmitted		= mlxsw_sp_ptp_transmitted,
 	.txhdr_len			= MLXSW_TXHDR_LEN,
 	.profile			= &mlxsw_sp1_config_profile,
 	.res_query_enabled		= true,
@@ -5047,6 +5065,7 @@ static struct mlxsw_driver mlxsw_sp2_driver = {
 	.resources_register		= mlxsw_sp2_resources_register,
 	.params_register		= mlxsw_sp2_params_register,
 	.params_unregister		= mlxsw_sp2_params_unregister,
+	.ptp_transmitted		= mlxsw_sp_ptp_transmitted,
 	.txhdr_len			= MLXSW_TXHDR_LEN,
 	.profile			= &mlxsw_sp2_config_profile,
 	.res_query_enabled		= true,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
index 8eca1ac03e7a..3af4573a4261 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
@@ -270,3 +270,9 @@ void mlxsw_sp1_ptp_receive(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
 {
 	mlxsw_sp_rx_listener_no_mark_func(skb, local_port, mlxsw_sp);
 }
+
+void mlxsw_sp1_ptp_transmitted(struct mlxsw_sp *mlxsw_sp,
+			       struct sk_buff *skb, u8 local_port)
+{
+	dev_kfree_skb_any(skb);
+}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.h
index 06bb303b5407..84955aa79c01 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.h
@@ -20,6 +20,9 @@ void mlxsw_sp1_ptp_clock_fini(struct mlxsw_sp_ptp_clock *clock);
 void mlxsw_sp1_ptp_receive(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
 			   u8 local_port);
 
+void mlxsw_sp1_ptp_transmitted(struct mlxsw_sp *mlxsw_sp,
+			       struct sk_buff *skb, u8 local_port);
+
 #else
 
 static inline struct mlxsw_sp_ptp_clock *
@@ -38,6 +41,12 @@ static inline void mlxsw_sp1_ptp_receive(struct mlxsw_sp *mlxsw_sp,
 	mlxsw_sp_rx_listener_no_mark_func(skb, local_port, mlxsw_sp);
 }
 
+static inline void mlxsw_sp1_ptp_transmitted(struct mlxsw_sp *mlxsw_sp,
+					     struct sk_buff *skb, u8 local_port)
+{
+	dev_kfree_skb_any(skb);
+}
+
 #endif
 
 static inline struct mlxsw_sp_ptp_clock *
@@ -56,4 +65,10 @@ static inline void mlxsw_sp2_ptp_receive(struct mlxsw_sp *mlxsw_sp,
 	mlxsw_sp_rx_listener_no_mark_func(skb, local_port, mlxsw_sp);
 }
 
+static inline void mlxsw_sp2_ptp_transmitted(struct mlxsw_sp *mlxsw_sp,
+					     struct sk_buff *skb, u8 local_port)
+{
+	dev_kfree_skb_any(skb);
+}
+
 #endif
-- 
2.20.1


^ permalink raw reply related

* [PATCH net-next 07/16] mlxsw: spectrum: PTP: Hook into packet receive path
From: Ido Schimmel @ 2019-06-27 13:52 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, petrm, mlxsw, Ido Schimmel
In-Reply-To: <20190627135259.7292-1-idosch@idosch.org>

From: Petr Machata <petrm@mellanox.com>

When configured, the Spectrum hardware can recognize PTP packets and
trap them to the CPU using dedicated traps, PTP0 and PTP1.

One reason to get PTP packets under dedicated traps is to have a
separate policer suitable for the amount of PTP traffic expected when
switch is operated as a boundary clock. For this, add two new trap
groups, MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP0 and _PTP1, and associate the
two PTP traps with these two groups.

In the driver, specifically for Spectrum-1, event PTP packets will need
to be paired up with their timestamps. Those arrive through a different
set of traps, added later in the patch set. To support this future use,
introduce a new PTP op, ptp_receive.

It is possible to configure which PTP messages should be trapped under
which PTP trap. On Spectrum systems, we will use PTP0 for event
packets (which need timestamping), and PTP1 for control packets (which
do not). Thus configure PTP0 trap with a custom callback that defers to
the ptp_receive op.

Additionally, L2 PTP packets are actually trapped through the LLDP trap,
not through any of the PTP traps. So treat the LLDP trap the same way as
the PTP0 trap. Unlike PTP traps, which are currently still disabled,
LLDP trap is active. Correspondingly, have all the implementations of
the ptp_receive op return true, which the handler treats as a signal to
forward the packet immediately.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h     |  2 +
 .../net/ethernet/mellanox/mlxsw/spectrum.c    | 49 +++++++++++++++----
 .../net/ethernet/mellanox/mlxsw/spectrum.h    |  2 +
 .../ethernet/mellanox/mlxsw/spectrum_ptp.c    |  6 +++
 .../ethernet/mellanox/mlxsw/spectrum_ptp.h    | 15 ++++++
 drivers/net/ethernet/mellanox/mlxsw/trap.h    |  2 +
 6 files changed, 67 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 8de9333e6eb1..76ff5b217c04 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -5292,6 +5292,8 @@ enum mlxsw_reg_htgt_trap_group {
 	MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_MLD,
 	MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_ND,
 	MLXSW_REG_HTGT_TRAP_GROUP_SP_LBERROR,
+	MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP0,
+	MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP1,
 };
 
 /* reg_htgt_trap_group
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 91486193454a..84f4077b4b37 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -147,6 +147,18 @@ struct mlxsw_sp_mlxfw_dev {
 	struct mlxsw_sp *mlxsw_sp;
 };
 
+struct mlxsw_sp_ptp_ops {
+	struct mlxsw_sp_ptp_clock *
+		(*clock_init)(struct mlxsw_sp *mlxsw_sp, struct device *dev);
+	void (*clock_fini)(struct mlxsw_sp_ptp_clock *clock);
+
+	/* Notify a driver that a packet that might be PTP was received. Driver
+	 * is responsible for freeing the passed-in SKB.
+	 */
+	void (*receive)(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
+			u8 local_port);
+};
+
 static int mlxsw_sp_component_query(struct mlxfw_dev *mlxfw_dev,
 				    u16 component_index, u32 *p_max_size,
 				    u8 *p_align_bits, u16 *p_max_write_size)
@@ -3947,8 +3959,8 @@ static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg,
 	}
 }
 
-static void mlxsw_sp_rx_listener_no_mark_func(struct sk_buff *skb,
-					      u8 local_port, void *priv)
+void mlxsw_sp_rx_listener_no_mark_func(struct sk_buff *skb,
+				       u8 local_port, void *priv)
 {
 	struct mlxsw_sp *mlxsw_sp = priv;
 	struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
@@ -4022,6 +4034,14 @@ static void mlxsw_sp_rx_listener_sample_func(struct sk_buff *skb, u8 local_port,
 	consume_skb(skb);
 }
 
+static void mlxsw_sp_rx_listener_ptp(struct sk_buff *skb, u8 local_port,
+				     void *priv)
+{
+	struct mlxsw_sp *mlxsw_sp = priv;
+
+	mlxsw_sp->ptp_ops->receive(mlxsw_sp, skb, local_port);
+}
+
 #define MLXSW_SP_RXL_NO_MARK(_trap_id, _action, _trap_group, _is_ctrl)	\
 	MLXSW_RXL(mlxsw_sp_rx_listener_no_mark_func, _trap_id, _action,	\
 		  _is_ctrl, SP_##_trap_group, DISCARD)
@@ -4043,7 +4063,8 @@ static const struct mlxsw_listener mlxsw_sp_listener[] = {
 	/* L2 traps */
 	MLXSW_SP_RXL_NO_MARK(STP, TRAP_TO_CPU, STP, true),
 	MLXSW_SP_RXL_NO_MARK(LACP, TRAP_TO_CPU, LACP, true),
-	MLXSW_SP_RXL_NO_MARK(LLDP, TRAP_TO_CPU, LLDP, true),
+	MLXSW_RXL(mlxsw_sp_rx_listener_ptp, LLDP, TRAP_TO_CPU,
+		  false, SP_LLDP, DISCARD),
 	MLXSW_SP_RXL_MARK(DHCP, MIRROR_TO_CPU, DHCP, false),
 	MLXSW_SP_RXL_MARK(IGMP_QUERY, MIRROR_TO_CPU, IGMP, false),
 	MLXSW_SP_RXL_NO_MARK(IGMP_V1_REPORT, TRAP_TO_CPU, IGMP, false),
@@ -4112,6 +4133,10 @@ static const struct mlxsw_listener mlxsw_sp_listener[] = {
 	/* NVE traps */
 	MLXSW_SP_RXL_MARK(NVE_ENCAP_ARP, TRAP_TO_CPU, ARP, false),
 	MLXSW_SP_RXL_NO_MARK(NVE_DECAP_ARP, TRAP_TO_CPU, ARP, false),
+	/* PTP traps */
+	MLXSW_RXL(mlxsw_sp_rx_listener_ptp, PTP0, TRAP_TO_CPU,
+		  false, SP_PTP0, DISCARD),
+	MLXSW_SP_RXL_NO_MARK(PTP1, TRAP_TO_CPU, PTP1, false),
 };
 
 static const struct mlxsw_listener mlxsw_sp1_listener[] = {
@@ -4166,6 +4191,14 @@ static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core)
 			rate = 1024;
 			burst_size = 7;
 			break;
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP0:
+			rate = 24 * 1024;
+			burst_size = 12;
+			break;
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP1:
+			rate = 19 * 1024;
+			burst_size = 12;
+			break;
 		default:
 			continue;
 		}
@@ -4204,6 +4237,7 @@ static int mlxsw_sp_trap_groups_set(struct mlxsw_core *mlxsw_core)
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_PIM:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP0:
 			priority = 5;
 			tc = 5;
 			break;
@@ -4221,6 +4255,7 @@ static int mlxsw_sp_trap_groups_set(struct mlxsw_core *mlxsw_core)
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_ND:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_RPF:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP1:
 			priority = 2;
 			tc = 2;
 			break;
@@ -4383,20 +4418,16 @@ static int mlxsw_sp_basic_trap_groups_set(struct mlxsw_core *mlxsw_core)
 	return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
 }
 
-struct mlxsw_sp_ptp_ops {
-	struct mlxsw_sp_ptp_clock *
-		(*clock_init)(struct mlxsw_sp *mlxsw_sp, struct device *dev);
-	void (*clock_fini)(struct mlxsw_sp_ptp_clock *clock);
-};
-
 static const struct mlxsw_sp_ptp_ops mlxsw_sp1_ptp_ops = {
 	.clock_init	= mlxsw_sp1_ptp_clock_init,
 	.clock_fini	= mlxsw_sp1_ptp_clock_fini,
+	.receive	= mlxsw_sp1_ptp_receive,
 };
 
 static const struct mlxsw_sp_ptp_ops mlxsw_sp2_ptp_ops = {
 	.clock_init	= mlxsw_sp2_ptp_clock_init,
 	.clock_fini	= mlxsw_sp2_ptp_clock_fini,
+	.receive	= mlxsw_sp2_ptp_receive,
 };
 
 static int mlxsw_sp_netdevice_event(struct notifier_block *unused,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 9136a86dc55f..139fb1c53f96 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -440,6 +440,8 @@ struct mlxsw_sp_fid *mlxsw_sp_bridge_fid_get(struct mlxsw_sp *mlxsw_sp,
 extern struct notifier_block mlxsw_sp_switchdev_notifier;
 
 /* spectrum.c */
+void mlxsw_sp_rx_listener_no_mark_func(struct sk_buff *skb,
+				       u8 local_port, void *priv);
 int mlxsw_sp_port_ets_set(struct mlxsw_sp_port *mlxsw_sp_port,
 			  enum mlxsw_reg_qeec_hr hr, u8 index, u8 next_index,
 			  bool dwrr, u8 dwrr_weight);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
index bb6c0cb25771..8eca1ac03e7a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
@@ -264,3 +264,9 @@ void mlxsw_sp1_ptp_clock_fini(struct mlxsw_sp_ptp_clock *clock)
 	cancel_delayed_work_sync(&clock->overflow_work);
 	kfree(clock);
 }
+
+void mlxsw_sp1_ptp_receive(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
+			   u8 local_port)
+{
+	mlxsw_sp_rx_listener_no_mark_func(skb, local_port, mlxsw_sp);
+}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.h
index 76fa00a4be75..06bb303b5407 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.h
@@ -17,6 +17,9 @@ mlxsw_sp1_ptp_clock_init(struct mlxsw_sp *mlxsw_sp, struct device *dev);
 
 void mlxsw_sp1_ptp_clock_fini(struct mlxsw_sp_ptp_clock *clock);
 
+void mlxsw_sp1_ptp_receive(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
+			   u8 local_port);
+
 #else
 
 static inline struct mlxsw_sp_ptp_clock *
@@ -29,6 +32,12 @@ static inline void mlxsw_sp1_ptp_clock_fini(struct mlxsw_sp_ptp_clock *clock)
 {
 }
 
+static inline void mlxsw_sp1_ptp_receive(struct mlxsw_sp *mlxsw_sp,
+					 struct sk_buff *skb, u8 local_port)
+{
+	mlxsw_sp_rx_listener_no_mark_func(skb, local_port, mlxsw_sp);
+}
+
 #endif
 
 static inline struct mlxsw_sp_ptp_clock *
@@ -41,4 +50,10 @@ static inline void mlxsw_sp2_ptp_clock_fini(struct mlxsw_sp_ptp_clock *clock)
 {
 }
 
+static inline void mlxsw_sp2_ptp_receive(struct mlxsw_sp *mlxsw_sp,
+					 struct sk_buff *skb, u8 local_port)
+{
+	mlxsw_sp_rx_listener_no_mark_func(skb, local_port, mlxsw_sp);
+}
+
 #endif
diff --git a/drivers/net/ethernet/mellanox/mlxsw/trap.h b/drivers/net/ethernet/mellanox/mlxsw/trap.h
index 451216dd7f6b..f05b7ff4b9df 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/trap.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/trap.h
@@ -17,6 +17,8 @@ enum {
 	MLXSW_TRAP_ID_MVRP = 0x15,
 	MLXSW_TRAP_ID_RPVST = 0x16,
 	MLXSW_TRAP_ID_DHCP = 0x19,
+	MLXSW_TRAP_ID_PTP0 = 0x28,
+	MLXSW_TRAP_ID_PTP1 = 0x29,
 	MLXSW_TRAP_ID_IGMP_QUERY = 0x30,
 	MLXSW_TRAP_ID_IGMP_V1_REPORT = 0x31,
 	MLXSW_TRAP_ID_IGMP_V2_REPORT = 0x32,
-- 
2.20.1


^ permalink raw reply related

* [PATCH net-next 06/16] mlxsw: spectrum: Add support for traps specific to Spectrum-1
From: Ido Schimmel @ 2019-06-27 13:52 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, petrm, mlxsw, Ido Schimmel
In-Reply-To: <20190627135259.7292-1-idosch@idosch.org>

From: Petr Machata <petrm@mellanox.com>

On Spectrum-1, timestamps for PTP packets are delivered through queues
of ingress and egress timestamps. There are two event traps
corresponding to activity on each of those queues. This mechanism is
absent on Spectrum-2, and therefore the traps should only be registered
on Spectrum-1.

Carry a chip-specific listener array in mlxsw_sp->listeners and
listeners_count. Register listeners from that array in
mlxsw_sp_traps_init(). Add a new listener array for Spectrum-1 traps and
configure the newly-added mlxsw_sp->listeners with this array.

The listener array is empty for now, the events will be added in a later
patch.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum.c    | 25 +++++++++++++++++--
 .../net/ethernet/mellanox/mlxsw/spectrum.h    |  2 ++
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 0119efe0ea7a..91486193454a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -4114,6 +4114,9 @@ static const struct mlxsw_listener mlxsw_sp_listener[] = {
 	MLXSW_SP_RXL_NO_MARK(NVE_DECAP_ARP, TRAP_TO_CPU, ARP, false),
 };
 
+static const struct mlxsw_listener mlxsw_sp1_listener[] = {
+};
+
 static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core)
 {
 	char qpcr_pl[MLXSW_REG_QPCR_LEN];
@@ -4302,12 +4305,28 @@ static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp)
 	if (err)
 		return err;
 
-	return mlxsw_sp_traps_register(mlxsw_sp, mlxsw_sp_listener,
-				       ARRAY_SIZE(mlxsw_sp_listener));
+	err = mlxsw_sp_traps_register(mlxsw_sp, mlxsw_sp_listener,
+				      ARRAY_SIZE(mlxsw_sp_listener));
+	if (err)
+		return err;
+
+	err = mlxsw_sp_traps_register(mlxsw_sp, mlxsw_sp->listeners,
+				      mlxsw_sp->listeners_count);
+	if (err)
+		goto err_extra_traps_init;
+
+	return 0;
+
+err_extra_traps_init:
+	mlxsw_sp_traps_unregister(mlxsw_sp, mlxsw_sp_listener,
+				  ARRAY_SIZE(mlxsw_sp_listener));
+	return err;
 }
 
 static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp)
 {
+	mlxsw_sp_traps_unregister(mlxsw_sp, mlxsw_sp->listeners,
+				  mlxsw_sp->listeners_count);
 	mlxsw_sp_traps_unregister(mlxsw_sp, mlxsw_sp_listener,
 				  ARRAY_SIZE(mlxsw_sp_listener));
 }
@@ -4566,6 +4585,8 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core,
 	mlxsw_sp->sb_vals = &mlxsw_sp1_sb_vals;
 	mlxsw_sp->port_type_speed_ops = &mlxsw_sp1_port_type_speed_ops;
 	mlxsw_sp->ptp_ops = &mlxsw_sp1_ptp_ops;
+	mlxsw_sp->listeners = mlxsw_sp1_listener;
+	mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp1_listener);
 
 	return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info);
 }
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 84f4276193b3..9136a86dc55f 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -175,6 +175,8 @@ struct mlxsw_sp {
 	const struct mlxsw_sp_sb_vals *sb_vals;
 	const struct mlxsw_sp_port_type_speed_ops *port_type_speed_ops;
 	const struct mlxsw_sp_ptp_ops *ptp_ops;
+	const struct mlxsw_listener *listeners;
+	size_t listeners_count;
 };
 
 static inline struct mlxsw_sp_upper *
-- 
2.20.1


^ permalink raw reply related

* [PATCH net-next 05/16] mlxsw: spectrum: Extract a helper for trap registration
From: Ido Schimmel @ 2019-06-27 13:52 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, petrm, mlxsw, Ido Schimmel
In-Reply-To: <20190627135259.7292-1-idosch@idosch.org>

From: Petr Machata <petrm@mellanox.com>

On Spectrum-1, timestamps for PTP packets are delivered through queues
of ingress and egress timestamps. There are two event traps
corresponding to activity on each of those queues. This mechanism is
absent on Spectrum-2, and therefore the traps should only be registered
on Spectrum-1.

Extract out of mlxsw_sp_traps_init() a generic helper,
mlxsw_sp_traps_register(), and likewise with _unregister(). The new helpers
will later be called with Spectrum-1-specific traps.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum.c    | 48 +++++++++++++------
 1 file changed, 33 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 3e8593824b33..0119efe0ea7a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -4251,22 +4251,16 @@ static int mlxsw_sp_trap_groups_set(struct mlxsw_core *mlxsw_core)
 	return 0;
 }
 
-static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp)
+static int mlxsw_sp_traps_register(struct mlxsw_sp *mlxsw_sp,
+				   const struct mlxsw_listener listeners[],
+				   size_t listeners_count)
 {
 	int i;
 	int err;
 
-	err = mlxsw_sp_cpu_policers_set(mlxsw_sp->core);
-	if (err)
-		return err;
-
-	err = mlxsw_sp_trap_groups_set(mlxsw_sp->core);
-	if (err)
-		return err;
-
-	for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener); i++) {
+	for (i = 0; i < listeners_count; i++) {
 		err = mlxsw_core_trap_register(mlxsw_sp->core,
-					       &mlxsw_sp_listener[i],
+					       &listeners[i],
 					       mlxsw_sp);
 		if (err)
 			goto err_listener_register;
@@ -4277,23 +4271,47 @@ static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp)
 err_listener_register:
 	for (i--; i >= 0; i--) {
 		mlxsw_core_trap_unregister(mlxsw_sp->core,
-					   &mlxsw_sp_listener[i],
+					   &listeners[i],
 					   mlxsw_sp);
 	}
 	return err;
 }
 
-static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp)
+static void mlxsw_sp_traps_unregister(struct mlxsw_sp *mlxsw_sp,
+				      const struct mlxsw_listener listeners[],
+				      size_t listeners_count)
 {
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener); i++) {
+	for (i = 0; i < listeners_count; i++) {
 		mlxsw_core_trap_unregister(mlxsw_sp->core,
-					   &mlxsw_sp_listener[i],
+					   &listeners[i],
 					   mlxsw_sp);
 	}
 }
 
+static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp)
+{
+	int err;
+
+	err = mlxsw_sp_cpu_policers_set(mlxsw_sp->core);
+	if (err)
+		return err;
+
+	err = mlxsw_sp_trap_groups_set(mlxsw_sp->core);
+	if (err)
+		return err;
+
+	return mlxsw_sp_traps_register(mlxsw_sp, mlxsw_sp_listener,
+				       ARRAY_SIZE(mlxsw_sp_listener));
+}
+
+static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp)
+{
+	mlxsw_sp_traps_unregister(mlxsw_sp, mlxsw_sp_listener,
+				  ARRAY_SIZE(mlxsw_sp_listener));
+}
+
 #define MLXSW_SP_LAG_SEED_INIT 0xcafecafe
 
 static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp)
-- 
2.20.1


^ permalink raw reply related

* [PATCH net-next 04/16] mlxsw: reg: Add Monitoring Global Configuration Register
From: Ido Schimmel @ 2019-06-27 13:52 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, petrm, mlxsw, Ido Schimmel
In-Reply-To: <20190627135259.7292-1-idosch@idosch.org>

From: Petr Machata <petrm@mellanox.com>

This register serves to configure global parameters of certain
monitoring operations. The following patches will use it to configure
that when PTP timestamps are delivered through the PTP FIFO traps, the
FIFO in question is cleared as well.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h | 27 +++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 197599890bdf..8de9333e6eb1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -9148,6 +9148,32 @@ static inline void mlxsw_reg_mprs_pack(char *payload, u16 parsing_depth,
 	mlxsw_reg_mprs_vxlan_udp_dport_set(payload, vxlan_udp_dport);
 }
 
+/* MOGCR - Monitoring Global Configuration Register
+ * ------------------------------------------------
+ */
+#define MLXSW_REG_MOGCR_ID 0x9086
+#define MLXSW_REG_MOGCR_LEN 0x20
+
+MLXSW_REG_DEFINE(mogcr, MLXSW_REG_MOGCR_ID, MLXSW_REG_MOGCR_LEN);
+
+/* reg_mogcr_ptp_iftc
+ * PTP Ingress FIFO Trap Clear
+ * The PTP_ING_FIFO trap provides MTPPTR with clr according
+ * to this value. Default 0.
+ * Reserved when IB switches and when SwitchX/-2, Spectrum-2
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mogcr, ptp_iftc, 0x00, 1, 1);
+
+/* reg_mogcr_ptp_eftc
+ * PTP Egress FIFO Trap Clear
+ * The PTP_EGR_FIFO trap provides MTPPTR with clr according
+ * to this value. Default 0.
+ * Reserved when IB switches and when SwitchX/-2, Spectrum-2
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mogcr, ptp_eftc, 0x00, 0, 1);
+
 /* MTPPPC - Time Precision Packet Port Configuration
  * -------------------------------------------------
  * This register serves for configuration of which PTP messages should be
@@ -10400,6 +10426,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
 	MLXSW_REG(mcda),
 	MLXSW_REG(mgpc),
 	MLXSW_REG(mprs),
+	MLXSW_REG(mogcr),
 	MLXSW_REG(mtpppc),
 	MLXSW_REG(mtpptr),
 	MLXSW_REG(mtptpt),
-- 
2.20.1


^ permalink raw reply related

* [PATCH net-next 03/16] mlxsw: reg: Add Time Precision Packet Timestamping Reading
From: Ido Schimmel @ 2019-06-27 13:52 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, petrm, mlxsw, Ido Schimmel
In-Reply-To: <20190627135259.7292-1-idosch@idosch.org>

From: Petr Machata <petrm@mellanox.com>

The MTPPTR is used for reading the per port PTP timestamp FIFO.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h | 110 ++++++++++++++++++++++
 1 file changed, 110 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 5c5f63289468..197599890bdf 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -9185,6 +9185,115 @@ static inline void mlxsw_reg_mtpppc_pack(char *payload, u16 ing, u16 egr)
 	mlxsw_reg_mtpppc_egr_timestamp_message_type_set(payload, egr);
 }
 
+/* MTPPTR - Time Precision Packet Timestamping Reading
+ * ---------------------------------------------------
+ * The MTPPTR is used for reading the per port PTP timestamp FIFO.
+ * There is a trap for packets which are latched to the timestamp FIFO, thus the
+ * SW knows which FIFO to read. Note that packets enter the FIFO before been
+ * trapped. The sequence number is used to synchronize the timestamp FIFO
+ * entries and the trapped packets.
+ * Reserved when Spectrum-2.
+ */
+
+#define MLXSW_REG_MTPPTR_ID 0x9091
+#define MLXSW_REG_MTPPTR_BASE_LEN 0x10 /* base length, without records */
+#define MLXSW_REG_MTPPTR_REC_LEN 0x10 /* record length */
+#define MLXSW_REG_MTPPTR_REC_MAX_COUNT 4
+#define MLXSW_REG_MTPPTR_LEN (MLXSW_REG_MTPPTR_BASE_LEN +		\
+		    MLXSW_REG_MTPPTR_REC_LEN * MLXSW_REG_MTPPTR_REC_MAX_COUNT)
+
+MLXSW_REG_DEFINE(mtpptr, MLXSW_REG_MTPPTR_ID, MLXSW_REG_MTPPTR_LEN);
+
+/* reg_mtpptr_local_port
+ * Not supported for CPU port.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, mtpptr, local_port, 0x00, 16, 8);
+
+enum mlxsw_reg_mtpptr_dir {
+	MLXSW_REG_MTPPTR_DIR_INGRESS,
+	MLXSW_REG_MTPPTR_DIR_EGRESS,
+};
+
+/* reg_mtpptr_dir
+ * Direction.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, mtpptr, dir, 0x00, 0, 1);
+
+/* reg_mtpptr_clr
+ * Clear the records.
+ * Access: OP
+ */
+MLXSW_ITEM32(reg, mtpptr, clr, 0x04, 31, 1);
+
+/* reg_mtpptr_num_rec
+ * Number of valid records in the response
+ * Range 0.. cap_ptp_timestamp_fifo
+ * Access: RO
+ */
+MLXSW_ITEM32(reg, mtpptr, num_rec, 0x08, 0, 4);
+
+/* reg_mtpptr_rec_message_type
+ * MessageType field as defined by IEEE 1588 Each bit corresponds to a value
+ * (e.g. Bit0: Sync, Bit1: Delay_Req)
+ * Access: RO
+ */
+MLXSW_ITEM32_INDEXED(reg, mtpptr, rec_message_type,
+		     MLXSW_REG_MTPPTR_BASE_LEN, 8, 4,
+		     MLXSW_REG_MTPPTR_REC_LEN, 0, false);
+
+/* reg_mtpptr_rec_domain_number
+ * DomainNumber field as defined by IEEE 1588
+ * Access: RO
+ */
+MLXSW_ITEM32_INDEXED(reg, mtpptr, rec_domain_number,
+		     MLXSW_REG_MTPPTR_BASE_LEN, 0, 8,
+		     MLXSW_REG_MTPPTR_REC_LEN, 0, false);
+
+/* reg_mtpptr_rec_sequence_id
+ * SequenceId field as defined by IEEE 1588
+ * Access: RO
+ */
+MLXSW_ITEM32_INDEXED(reg, mtpptr, rec_sequence_id,
+		     MLXSW_REG_MTPPTR_BASE_LEN, 0, 16,
+		     MLXSW_REG_MTPPTR_REC_LEN, 0x4, false);
+
+/* reg_mtpptr_rec_timestamp_high
+ * Timestamp of when the PTP packet has passed through the port Units of PLL
+ * clock time.
+ * For Spectrum-1 the PLL clock is 156.25Mhz and PLL clock time is 6.4nSec.
+ * Access: RO
+ */
+MLXSW_ITEM32_INDEXED(reg, mtpptr, rec_timestamp_high,
+		     MLXSW_REG_MTPPTR_BASE_LEN, 0, 32,
+		     MLXSW_REG_MTPPTR_REC_LEN, 0x8, false);
+
+/* reg_mtpptr_rec_timestamp_low
+ * See rec_timestamp_high.
+ * Access: RO
+ */
+MLXSW_ITEM32_INDEXED(reg, mtpptr, rec_timestamp_low,
+		     MLXSW_REG_MTPPTR_BASE_LEN, 0, 32,
+		     MLXSW_REG_MTPPTR_REC_LEN, 0xC, false);
+
+static inline void mlxsw_reg_mtpptr_unpack(const char *payload,
+					   unsigned int rec,
+					   u8 *p_message_type,
+					   u8 *p_domain_number,
+					   u16 *p_sequence_id,
+					   u64 *p_timestamp)
+{
+	u32 timestamp_high, timestamp_low;
+
+	*p_message_type = mlxsw_reg_mtpptr_rec_message_type_get(payload, rec);
+	*p_domain_number = mlxsw_reg_mtpptr_rec_domain_number_get(payload, rec);
+	*p_sequence_id = mlxsw_reg_mtpptr_rec_sequence_id_get(payload, rec);
+	timestamp_high = mlxsw_reg_mtpptr_rec_timestamp_high_get(payload, rec);
+	timestamp_low = mlxsw_reg_mtpptr_rec_timestamp_low_get(payload, rec);
+	*p_timestamp = (u64)timestamp_high << 32 | timestamp_low;
+}
+
 /* MTPTPT - Monitoring Precision Time Protocol Trap Register
  * ---------------------------------------------------------
  * This register is used for configuring under which trap to deliver PTP
@@ -10292,6 +10401,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
 	MLXSW_REG(mgpc),
 	MLXSW_REG(mprs),
 	MLXSW_REG(mtpppc),
+	MLXSW_REG(mtpptr),
 	MLXSW_REG(mtptpt),
 	MLXSW_REG(mgpir),
 	MLXSW_REG(tngcr),
-- 
2.20.1


^ permalink raw reply related

* [PATCH net-next 02/16] mlxsw: reg: Add Monitoring Precision Time Protocol Trap Register
From: Ido Schimmel @ 2019-06-27 13:52 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, petrm, mlxsw, Ido Schimmel
In-Reply-To: <20190627135259.7292-1-idosch@idosch.org>

From: Petr Machata <petrm@mellanox.com>

This register is used for configuring under which trap to deliver PTP
packets depending on type of the packet.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h | 39 +++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 971e336aa9ac..5c5f63289468 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -9185,6 +9185,44 @@ static inline void mlxsw_reg_mtpppc_pack(char *payload, u16 ing, u16 egr)
 	mlxsw_reg_mtpppc_egr_timestamp_message_type_set(payload, egr);
 }
 
+/* MTPTPT - Monitoring Precision Time Protocol Trap Register
+ * ---------------------------------------------------------
+ * This register is used for configuring under which trap to deliver PTP
+ * packets depending on type of the packet.
+ */
+#define MLXSW_REG_MTPTPT_ID 0x9092
+#define MLXSW_REG_MTPTPT_LEN 0x08
+
+MLXSW_REG_DEFINE(mtptpt, MLXSW_REG_MTPTPT_ID, MLXSW_REG_MTPTPT_LEN);
+
+enum mlxsw_reg_mtptpt_trap_id {
+	MLXSW_REG_MTPTPT_TRAP_ID_PTP0,
+	MLXSW_REG_MTPTPT_TRAP_ID_PTP1,
+};
+
+/* reg_mtptpt_trap_id
+ * Trap id.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, mtptpt, trap_id, 0x00, 0, 4);
+
+/* reg_mtptpt_message_type
+ * Bitwise vector of PTP message types to trap. This is a necessary but
+ * non-sufficient condition since need to enable also per port. See MTPPPC.
+ * Message types are defined by IEEE 1588 Each bit corresponds to a value (e.g.
+ * Bit0: Sync, Bit1: Delay_Req)
+ */
+MLXSW_ITEM32(reg, mtptpt, message_type, 0x04, 0, 16);
+
+static inline void mlxsw_reg_mtptptp_pack(char *payload,
+					  enum mlxsw_reg_mtptpt_trap_id trap_id,
+					  u16 message_type)
+{
+	MLXSW_REG_ZERO(mtptpt, payload);
+	mlxsw_reg_mtptpt_trap_id_set(payload, trap_id);
+	mlxsw_reg_mtptpt_message_type_set(payload, message_type);
+}
+
 /* MGPIR - Management General Peripheral Information Register
  * ----------------------------------------------------------
  * MGPIR register allows software to query the hardware and
@@ -10254,6 +10292,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
 	MLXSW_REG(mgpc),
 	MLXSW_REG(mprs),
 	MLXSW_REG(mtpppc),
+	MLXSW_REG(mtptpt),
 	MLXSW_REG(mgpir),
 	MLXSW_REG(tngcr),
 	MLXSW_REG(tnumt),
-- 
2.20.1


^ permalink raw reply related

* [PATCH net-next 01/16] mlxsw: reg: Add Monitoring Time Precision Packet Port Configuration Register
From: Ido Schimmel @ 2019-06-27 13:52 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, petrm, mlxsw, Ido Schimmel
In-Reply-To: <20190627135259.7292-1-idosch@idosch.org>

From: Petr Machata <petrm@mellanox.com>

This register serves for configuration of which PTP messages should be
timestamped. This is a global configuration, despite the register name.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h | 38 +++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index e5f6bfd8a35a..971e336aa9ac 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -9148,6 +9148,43 @@ static inline void mlxsw_reg_mprs_pack(char *payload, u16 parsing_depth,
 	mlxsw_reg_mprs_vxlan_udp_dport_set(payload, vxlan_udp_dport);
 }
 
+/* MTPPPC - Time Precision Packet Port Configuration
+ * -------------------------------------------------
+ * This register serves for configuration of which PTP messages should be
+ * timestamped. This is a global configuration, despite the register name.
+ *
+ * Reserved when Spectrum-2.
+ */
+#define MLXSW_REG_MTPPPC_ID 0x9090
+#define MLXSW_REG_MTPPPC_LEN 0x28
+
+MLXSW_REG_DEFINE(mtpppc, MLXSW_REG_MTPPPC_ID, MLXSW_REG_MTPPPC_LEN);
+
+/* reg_mtpppc_ing_timestamp_message_type
+ * Bitwise vector of PTP message types to timestamp at ingress.
+ * MessageType field as defined by IEEE 1588
+ * Each bit corresponds to a value (e.g. Bit0: Sync, Bit1: Delay_Req)
+ * Default all 0
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mtpppc, ing_timestamp_message_type, 0x08, 0, 16);
+
+/* reg_mtpppc_egr_timestamp_message_type
+ * Bitwise vector of PTP message types to timestamp at egress.
+ * MessageType field as defined by IEEE 1588
+ * Each bit corresponds to a value (e.g. Bit0: Sync, Bit1: Delay_Req)
+ * Default all 0
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mtpppc, egr_timestamp_message_type, 0x0C, 0, 16);
+
+static inline void mlxsw_reg_mtpppc_pack(char *payload, u16 ing, u16 egr)
+{
+	MLXSW_REG_ZERO(mtpppc, payload);
+	mlxsw_reg_mtpppc_ing_timestamp_message_type_set(payload, ing);
+	mlxsw_reg_mtpppc_egr_timestamp_message_type_set(payload, egr);
+}
+
 /* MGPIR - Management General Peripheral Information Register
  * ----------------------------------------------------------
  * MGPIR register allows software to query the hardware and
@@ -10216,6 +10253,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
 	MLXSW_REG(mcda),
 	MLXSW_REG(mgpc),
 	MLXSW_REG(mprs),
+	MLXSW_REG(mtpppc),
 	MLXSW_REG(mgpir),
 	MLXSW_REG(tngcr),
 	MLXSW_REG(tnumt),
-- 
2.20.1


^ permalink raw reply related

* [PATCH net-next 00/16] mlxsw: PTP timestamping support
From: Ido Schimmel @ 2019-06-27 13:52 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, petrm, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

This is the second patchset adding PTP support in mlxsw. Next patchset
will add PTP shapers which are required to maintain accuracy under rates
lower than 40Gb/s, while subsequent patchsets will add tracepoints and
selftests.

Petr says:

This patch set introduces support for retrieving and processing hardware
timestamps for PTP packets.

The way PTP timestamping works on Spectrum-1 is that there are two queues
associated with each front panel port. When a packet is timestamped, the
timestamp is put to one of the queues: timestamps for transmitted packets
to one and for received packets to the other. Activity on these queues is
signaled through the events PTP_ING_FIFO and PTP_EGR_FIFO.

Packets themselves arrive through two traps: PTP0 and PTP1. It is possible
to configure which PTP messages should be trapped under which PTP trap. On
Spectrum systems, mlxsw will use PTP0 for event messages (which need
timestamping), and PTP1 for general messages (which do not).

There are therefore four relevant traps: receive of PTP event resp. general
message, and receive of timestamp for a transmitted resp. received PTP
packet. The obvious point where to put the new logic is a custom listener
to the mentioned traps.

Besides handling ingress traffic (be in packets or timestamps), the driver
also needs to handle timestamping of transmitted packets. One option would
be to invoke the relevant logic from mlxsw_core_ptp_transmitted(). However
on Spectrum-2, the timestamps are actually delivered through the completion
queue, and for that reason this patchset opts to invoke the logic from the
PCI code, via core and the driver, to a chip-specific operation. That way
the invocation will be done in a place where a Spectrum-2 implementation
will have an opportunity to extract the timestamp.

As indicated above, the PTP FIFO signaling happens independently from
packet delivery. A packet corresponding to any given timestamp could be
delivered sooner or later than the timestamp itself. Additionally, the
queues are only four elements deep, and it is therefore possible that the
timestamp for a delivered packet never arrives at all. Similarly a PTP
packet might be dropped due to CPU traffic pressure, and never be delivered
even if the corresponding timestamp was.

The driver thus needs to hold a cache of as-yet-unmatched SKBs and
timestamps. The first piece to arrive (be it timestamp or SKB) is put to
this cache. When the other piece arrives, the timestamp is attached to the
SKB and that is passed on. A delayed work is run at regular intervals to
prune the old unmatched entries.

As mentioned above, the mechanism for timestamp delivery changes on
Spectrum-2, where timestamps are part of completion queue elements, and all
packets are timestamped. All this bookkeeping is therefore unnecessary on
Spectrum-2. For this reason, this patchset spends some time introducing
Spectrum-1 specific artifacts such as a possibility to register a given
trap only on Spectrum-1.

Patches #1-#4 describe new registers.

Patches #5 and #6 introduce the possibility to register certain traps
only on some systems. The list of Spectrum-1 specific traps is left empty
at this point.

Patch #7 hooks into packet receive path by registering PTP traps
and appropriate handlers (that however do nothing of substance yet).

Patch #8 adds a helper to allow storing custom data to SKB->cb.

Patch #9 adds a call into the PCI completion queue handler that invokes,
via core and spectrum code, a PTP transmit handler. (Which also does not do
anything interesting yet.)

Patch #10 introduces code to invoke PTP initialization and adds data types
for the cache of unmatched entries.

Patches #11 and #12 implement the timestamping itself. In #11, the PHC
spin_locks are converted to _bh variants, because unlike normal PHC path,
which runs in process context, timestamp processing runs as soft interrupt.
Then #12 introduces the code for saving and retrieval of unmatched entries,
invokes PTP classifier to identify packets of interest, registers timestamp
FIFO events, and handles decoding and attaching timestamps to packets.

Patch #13 introduces a garbage collector for left-behind entries that have
not been matched for about a second.

In patch #14, PTP message types are configured to arrive as PTP0
(events) or PTP1 (everything else) as appropriate. At this point, the PTP
packets start arriving through the traps, but because PTP is disabled and
there is no way to enable it yet, they are always just passed to the usual
receive path right away.

Finally patches #15 and #16 add the plumbing to actually make it possible
to enable this code through SIOCSHWTSTAMP ioctl, and to advertise the
hardware timestamping capabilities through ethtool.

Petr Machata (16):
  mlxsw: reg: Add Monitoring Time Precision Packet Port Configuration
    Register
  mlxsw: reg: Add Monitoring Precision Time Protocol Trap Register
  mlxsw: reg: Add Time Precision Packet Timestamping Reading
  mlxsw: reg: Add Monitoring Global Configuration Register
  mlxsw: spectrum: Extract a helper for trap registration
  mlxsw: spectrum: Add support for traps specific to Spectrum-1
  mlxsw: spectrum: PTP: Hook into packet receive path
  mlxsw: core: Add support for using SKB control buffer
  mlxsw: pci: PTP: Hook into packet transmit path
  mlxsw: spectrum: PTP: Add PTP initialization / finalization
  mlxsw: spectrum: PTP: Disable BH when working with PHC
  mlxsw: spectrum: PTP: Support timestamping on Spectrum-1
  mlxsw: spectrum: PTP: Garbage-collect unmatched entries
  mlxsw: spectrum: PTP: Configure PTP traps and FIFO events
  mlxsw: spectrum: PTP: Support SIOCGHWTSTAMP, SIOCSHWTSTAMP ioctls
  mlxsw: spectrum: PTP: Support ethtool get_ts_info

 drivers/net/ethernet/mellanox/mlxsw/Kconfig   |   1 +
 drivers/net/ethernet/mellanox/mlxsw/core.c    |   9 +
 drivers/net/ethernet/mellanox/mlxsw/core.h    |  19 +
 drivers/net/ethernet/mellanox/mlxsw/pci.c     |  17 +-
 drivers/net/ethernet/mellanox/mlxsw/reg.h     | 216 ++++++
 .../net/ethernet/mellanox/mlxsw/spectrum.c    | 290 ++++++-
 .../net/ethernet/mellanox/mlxsw/spectrum.h    |  11 +
 .../ethernet/mellanox/mlxsw/spectrum_ptp.c    | 711 +++++++++++++++++-
 .../ethernet/mellanox/mlxsw/spectrum_ptp.h    | 136 +++-
 .../net/ethernet/mellanox/mlxsw/switchx2.c    |   2 +
 drivers/net/ethernet/mellanox/mlxsw/trap.h    |   6 +
 11 files changed, 1378 insertions(+), 40 deletions(-)

-- 
2.20.1


^ permalink raw reply

* Re: [RFC PATCH 1/1] Documentation: net: dsa: b53: Describe b53 configuration
From: Andrew Lunn @ 2019-06-27 13:49 UTC (permalink / raw)
  To: Benedikt Spranger
  Cc: Florian Fainelli, netdev, Sebastian Andrzej Siewior,
	Kurt Kanzenbach, Vivien Didelot
In-Reply-To: <20190627101506.19727-2-b.spranger@linutronix.de>

On Thu, Jun 27, 2019 at 12:15:06PM +0200, Benedikt Spranger wrote:

Hi Benedikt

> +Configuration with tagging support
> +----------------------------------
> +
> +The tagging based configuration is desired.
> +
> +To use the b53 DSA driver some configuration need to be performed. As
> +example configuration the following scenarios are used:
> +
> +*single port*
> +  Every switch port acts as a different configurable ethernet port
> +
> +*bridge*
> +  Every switch port is part of one configurable ethernet bridge
> +
> +*gateway*
> +  Every switch port except one upstream port is part of a configurable
> +  ethernet bridge.
> +  The upstream port acts as different configurable ethernet port.
> +
> +All configurations are performed with tools from iproute2, wich is available at
> +https://www.kernel.org/pub/linux/utils/net/iproute2/
> +
> +In this documentation the following ethernet ports are used:
> +
> +*eth0*
> +  CPU port

In DSA terminology, this is the master interface. The switch port
which the master is connected to is called the CPU port. So you are
causing confusion with DSA terms here.

> +
> +*LAN1*
> +  a switch port
> +
> +*LAN2*
> +  another switch port
> +
> +*WAN*
> +  A switch port dedicated as upstream port

These are all slave interfaces, when using DSA terms.

> +Further ethernet ports can be configured similar.
> +The configured IPs and networks are:
> +
> +*single port*
> +  *  wan: 192.0.2.1/30 (192.0.2.0 - 192.0.2.3)
> +  * lan1: 192.0.2.5/30 (192.0.2.4 - 192.0.2.7)
> +  * lan2: 192.0.2.9/30 (192.0.2.8 - 192.0.2.11)
> +
> +*bridge*
> +  * br0: 192.0.2.129/25 (192.0.2.128 - 192.0.2.255)
> +
> +*gateway*
> +  * br0: 192.0.2.129/25 (192.0.2.128 - 192.0.2.255)
> +  * wan: 192.0.2.1/30 (192.0.2.0 - 192.0.2.3)
> +
> +single port
> +~~~~~~~~~~~
> +
> +.. code-block:: sh
> +
> +  # configure each interface
> +  ip addr add 192.0.2.1/30 dev wan
> +  ip addr add 192.0.2.5/30 dev lan1
> +  ip addr add 192.0.2.9/30 dev lan2
> +
> +  # The master interface needs to be brought up before the slave ports.
> +  ip link set eth0 up
> +
> +  # bring up the slave interfaces
> +  ip link set wan up
> +  ip link set lan1 up
> +  ip link set lan2 up
> +
> +bridge
> +~~~~~~
> +
> +.. code-block:: sh
> +
> +  # create bridge
> +  ip link add name br0 type bridge
> +
> +  # add ports to bridge
> +  ip link set dev wan master br0
> +  ip link set dev lan1 master br0
> +  ip link set dev lan2 master br0
> +
> +  # configure the bridge
> +  ip addr add 192.0.2.129/25 dev br0
> +
> +  # The master interface needs to be brought up before the slave ports.
> +  ip link set eth0 up
> +
> +  # bring up the slave interfaces
> +  ip link set wan up
> +  ip link set lan1 up
> +  ip link set lan2 up

I would probably do this in a different order. Bring the master up
first, then the slaves. Then enslave the slaves to bridge, and lastly
configure the bridge.

> +
> +  # bring up the bridge
> +  ip link set dev br0 up
> +
> +gateway
> +~~~~~~~
> +
> +.. code-block:: sh
> +
> +  # create bridge
> +  ip link add name br0 type bridge
> +
> +  # add ports to bridge
> +  ip link set dev lan1 master br0
> +  ip link set dev lan2 master br0
> +
> +  # configure the bridge
> +  ip addr add 192.0.2.129/25 dev br0
> +
> +  # configure the upstream port
> +  ip addr add 192.0.2.1/30 dev wan
> +
> +  # The master interface needs to be brought up before the slave ports.
> +  ip link set eth0 up
> +
> +  # bring up the slave interfaces
> +  ip link set wan up
> +  ip link set lan1 up
> +  ip link set lan2 up
> +
> +  # bring up the bridge
> +  ip link set dev br0 up

It would be good to add a note that there is nothing specific to the
B53 here. This same process will work for all DSA drivers which
support tagging, which is actually the majority.

I also tell people that once you configure the master interface up,
they should just use the slave interfaces a normal linux
interfaces. The fact they are on a switch does not matter, and should
not matter. Just use them as normal.

	Andrew

^ permalink raw reply

* Re: [PATCH 2/2 nf-next] netfilter:nft_meta: add NFT_META_VLAN support
From: wenxu @ 2019-06-27 13:37 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: fw, netfilter-devel, netdev
In-Reply-To: <20190627123550.vx7r4rmzduzabig6@salvia>


在 2019/6/27 20:35, Pablo Neira Ayuso 写道:
> On Thu, Jun 27, 2019 at 10:09:17AM +0800, wenxu@ucloud.cn wrote:
>> From: wenxu <wenxu@ucloud.cn>
>>
>> This patch provide a meta vlan to set the vlan tag of the packet.
>>
>> for q-in-q vlan id 20:
>> meta vlan set 0x88a8:20
> Actually, I think this is not very useful for stacked vlan since this
> just sets/mangles the existing meta vlan data.
>
> We'll need infrastructure that uses skb_vlan_push() and _pop().
>
> Patch looks good anyway, such infrastructure to push/pop can be added
> later on.
>
> Thanks.

yes, It's just ste/mangle the meta vlan data. I just wonder if we set for stacked vlan.

vlan meta 0x88a8:20. The packet should contain a 0x8100 vlan tag, we just push the

inner vlan and the the vlan meta with the outer 0x88a8:20. Or the packet don't contain

only vlan tag, we add a inner 0x8100:20 tag and outer 0x88a8:20 tag?

So wen should check for this

>
>> set the default 0x8100 vlan type with vlan id 20
>> meta vlan set 20
>>
>> Signed-off-by: wenxu <wenxu@ucloud.cn>
>> ---
>>  include/uapi/linux/netfilter/nf_tables.h |  4 ++++
>>  net/netfilter/nft_meta.c                 | 27 ++++++++++++++++++++++++++-
>>  2 files changed, 30 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
>> index 0b18646..cf037f2 100644
>> --- a/include/uapi/linux/netfilter/nf_tables.h
>> +++ b/include/uapi/linux/netfilter/nf_tables.h
>> @@ -797,6 +797,7 @@ enum nft_exthdr_attributes {
>>   * @NFT_META_OIFKIND: packet output interface kind name (dev->rtnl_link_ops->kind)
>>   * @NFT_META_BRI_PVID: packet input bridge port pvid
>>   * @NFT_META_BRI_VLAN_PROTO: packet input bridge vlan proto
>> + * @NFT_META_VLAN: packet vlan metadata
>>   */
>>  enum nft_meta_keys {
>>  	NFT_META_LEN,
>> @@ -829,6 +830,7 @@ enum nft_meta_keys {
>>  	NFT_META_OIFKIND,
>>  	NFT_META_BRI_PVID,
>>  	NFT_META_BRI_VLAN_PROTO,
>> +	NFT_META_VLAN,
>>  };
>>  
>>  /**
>> @@ -895,12 +897,14 @@ enum nft_hash_attributes {
>>   * @NFTA_META_DREG: destination register (NLA_U32)
>>   * @NFTA_META_KEY: meta data item to load (NLA_U32: nft_meta_keys)
>>   * @NFTA_META_SREG: source register (NLA_U32)
>> + * @NFTA_META_SREG2: source register (NLA_U32)
>>   */
>>  enum nft_meta_attributes {
>>  	NFTA_META_UNSPEC,
>>  	NFTA_META_DREG,
>>  	NFTA_META_KEY,
>>  	NFTA_META_SREG,
>> +	NFTA_META_SREG2,
>>  	__NFTA_META_MAX
>>  };
>>  #define NFTA_META_MAX		(__NFTA_META_MAX - 1)
>> diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
>> index e3adf6a..29a6679 100644
>> --- a/net/netfilter/nft_meta.c
>> +++ b/net/netfilter/nft_meta.c
>> @@ -28,7 +28,10 @@ struct nft_meta {
>>  	enum nft_meta_keys	key:8;
>>  	union {
>>  		enum nft_registers	dreg:8;
>> -		enum nft_registers	sreg:8;
>> +		struct {
>> +			enum nft_registers	sreg:8;
>> +			enum nft_registers	sreg2:8;
>> +		};
>>  	};
>>  };
>>  
>> @@ -312,6 +315,17 @@ static void nft_meta_set_eval(const struct nft_expr *expr,
>>  		skb->secmark = value;
>>  		break;
>>  #endif
>> +	case NFT_META_VLAN: {
>> +		u32 *sreg2 = &regs->data[meta->sreg2];
>> +		__be16 vlan_proto;
>> +		u16 vlan_tci;
>> +
>> +		vlan_tci = nft_reg_load16(sreg);
>> +		vlan_proto = nft_reg_load16(sreg2);
>> +
>> +		__vlan_hwaccel_put_tag(skb, vlan_proto, vlan_tci);
>> +		break;
>> +	}
>>  	default:
>>  		WARN_ON(1);
>>  	}
>> @@ -321,6 +335,7 @@ static void nft_meta_set_eval(const struct nft_expr *expr,
>>  	[NFTA_META_DREG]	= { .type = NLA_U32 },
>>  	[NFTA_META_KEY]		= { .type = NLA_U32 },
>>  	[NFTA_META_SREG]	= { .type = NLA_U32 },
>> +	[NFTA_META_SREG2]	= { .type = NLA_U32 },
>>  };
>>  
>>  static int nft_meta_get_init(const struct nft_ctx *ctx,
>> @@ -483,6 +498,13 @@ static int nft_meta_set_init(const struct nft_ctx *ctx,
>>  	case NFT_META_PKTTYPE:
>>  		len = sizeof(u8);
>>  		break;
>> +	case NFT_META_VLAN:
>> +		len = sizeof(u16);
>> +		priv->sreg2 = nft_parse_register(tb[NFTA_META_SREG2]);
>> +		err = nft_validate_register_load(priv->sreg2, len);
>> +		if (err < 0)
>> +			return err;
>> +		break;
>>  	default:
>>  		return -EOPNOTSUPP;
>>  	}
>> @@ -521,6 +543,9 @@ static int nft_meta_set_dump(struct sk_buff *skb, const struct nft_expr *expr)
>>  		goto nla_put_failure;
>>  	if (nft_dump_register(skb, NFTA_META_SREG, priv->sreg))
>>  		goto nla_put_failure;
>> +	if (priv->key == NFT_META_VLAN &&
>> +	    nft_dump_register(skb, NFTA_META_SREG2, priv->sreg2))
>> +		goto nla_put_failure;
>>  
>>  	return 0;
>>  
>> -- 
>> 1.8.3.1
>>

^ permalink raw reply

* [PATCH net 1/1] net: openvswitch: fix csum updates for MPLS actions
From: John Hurley @ 2019-06-27 13:37 UTC (permalink / raw)
  To: netdev
  Cc: davem, pshelar, simon.horman, jakub.kicinski, oss-drivers,
	John Hurley

Skbs may have their checksum value populated by HW. If this is a checksum
calculated over the entire packet then the CHECKSUM_COMPLETE field is
marked. Changes to the data pointer on the skb throughout the network
stack still try to maintain this complete csum value if it is required
through functions such as skb_postpush_rcsum.

The MPLS actions in Open vSwitch modify a CHECKSUM_COMPLETE value when
changes are made to packet data without a push or a pull. This occurs when
the ethertype of the MAC header is changed or when MPLS lse fields are
modified.

The modification is carried out using the csum_partial function to get the
csum of a buffer and add it into the larger checksum. The buffer is an
inversion of the data to be removed followed by the new data. Because the
csum is calculated over 16 bits and these values align with 16 bits, the
effect is the removal of the old value from the CHECKSUM_COMPLETE and
addition of the new value.

However, the csum fed into the function and the outcome of the
calculation are also inverted. This would only make sense if it was the
new value rather than the old that was inverted in the input buffer.

Fix the issue by removing the bit inverts in the csum_partial calculation.

The bug was verified and the fix tested by comparing the folded value of
the updated CHECKSUM_COMPLETE value with the folded value of a full
software checksum calculation (reset skb->csum to 0 and run
skb_checksum_complete(skb)). Prior to the fix the outcomes differed but
after they produce the same result.

Fixes: 25cd9ba0abc0 ("openvswitch: Add basic MPLS support to kernel")
Fixes: bc7cc5999fd3 ("openvswitch: update checksum in {push,pop}_mpls")
Signed-off-by: John Hurley <john.hurley@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
---
 net/openvswitch/actions.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 151518d..bd13146 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -166,8 +166,7 @@ static void update_ethertype(struct sk_buff *skb, struct ethhdr *hdr,
 	if (skb->ip_summed == CHECKSUM_COMPLETE) {
 		__be16 diff[] = { ~(hdr->h_proto), ethertype };
 
-		skb->csum = ~csum_partial((char *)diff, sizeof(diff),
-					~skb->csum);
+		skb->csum = csum_partial((char *)diff, sizeof(diff), skb->csum);
 	}
 
 	hdr->h_proto = ethertype;
@@ -259,8 +258,7 @@ static int set_mpls(struct sk_buff *skb, struct sw_flow_key *flow_key,
 	if (skb->ip_summed == CHECKSUM_COMPLETE) {
 		__be32 diff[] = { ~(stack->label_stack_entry), lse };
 
-		skb->csum = ~csum_partial((char *)diff, sizeof(diff),
-					  ~skb->csum);
+		skb->csum = csum_partial((char *)diff, sizeof(diff), skb->csum);
 	}
 
 	stack->label_stack_entry = lse;
-- 
2.7.4


^ permalink raw reply related

* RE: [PATCH net-next 10/10] net: stmmac: Try to get C45 PHY if everything else fails
From: Jose Abreu @ 2019-06-27 13:33 UTC (permalink / raw)
  To: Andrew Lunn, Jose Abreu
  Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Joao Pinto,
	David S . Miller, Giuseppe Cavallaro, Alexandre Torgue
In-Reply-To: <20190627132340.GC31189@lunn.ch>

From: Andrew Lunn <andrew@lunn.ch>

> There have been some drivers gaining patches for ACPI. That is
> probably the better long term solution, ask ACPI where is the PHY and
> what MDIO protocol to use to talk to it.

Hmmm, I'm not sure this is going to work that way ...

My setup is a PCI EP which is hot-pluggable and as far as I know ACPI 
has only static content (????)

^ permalink raw reply

* Re: [PATCH net-next 10/10] net: stmmac: Try to get C45 PHY if everything else fails
From: Andrew Lunn @ 2019-06-27 13:23 UTC (permalink / raw)
  To: Jose Abreu
  Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Joao Pinto,
	David S . Miller, Giuseppe Cavallaro, Alexandre Torgue
In-Reply-To: <BN8PR12MB3266A8396ACA97484A5E0CE7D3FD0@BN8PR12MB3266.namprd12.prod.outlook.com>

On Thu, Jun 27, 2019 at 07:54:14AM +0000, Jose Abreu wrote:
> From: Andrew Lunn <andrew@lunn.ch>
> 
> > On Wed, Jun 26, 2019 at 03:47:44PM +0200, Jose Abreu wrote:
> > > On PCI based setups that are connected to C45 PHY we won't have DT
> > > bindings specifying what's the correct PHY type.
> > 
> > You can associate a DT node to a PCI device. The driver does not have
> > to do anything special, the PCI core code does all the work.
> > 
> > As an example look at imx6q-zii-rdu2.dts, node &pcie, which has an
> > intel i210 on the pcie bus, and we need a handle to it.
> 
> That's for ARM but I'm using X86_64 which only has ACPI :/

Hi Jose

There have been some drivers gaining patches for ACPI. That is
probably the better long term solution, ask ACPI where is the PHY and
what MDIO protocol to use to talk to it.

	 Andrew

^ permalink raw reply

* [BUG] net: dm9600: false link status
From: Corentin Labbe @ 2019-06-27 13:21 UTC (permalink / raw)
  To: jacmet, davem, netdev, linux-usb; +Cc: linux-kernel

Hello

I own an USB dongle which is a "Davicom DM96xx USB 10/100 Ethernet".
According to the CHIP_ID, it is a DM9620.

Since I needed for bringing network to uboot for a board, I have started to create its uboot's driver.
My uboot driver is based on the dm9600 Linux driver.

The dongle was working but very very slowy (24Kib/s).
After some debug i found that the main problem was that it always link to 10Mbit/s Half-duplex. (according to the MAC registers)

For checking the status of the dongle I have plugged it on a Linux box which give me:
dm9601 6-2:1.0 enp0s29f0u2: link up, 100Mbps, full-duplex, lpa 0xFFFF

But in fact the Linux driver is tricked.

I have added debug of MDIO write/read and got:
[157550.926974] dm9601 6-2:1.0 (unnamed net_device) (uninitialized): dm9601_mdio_write() phy_id=0x00, loc=0x00, val=0x8000
[157550.931962] dm9601 6-2:1.0 (unnamed net_device) (uninitialized): dm9601_mdio_write() phy_id=0x00, loc=0x04, val=0x05e1
[157550.951967] dm9601 6-2:1.0 (unnamed net_device) (uninitialized): dm9601_mdio_read() phy_id=0x00, loc=0x00, returns=0xffff
[157550.951971] dm9601 6-2:1.0 (unnamed net_device) (uninitialized): dm9601_mdio_write() phy_id=0x00, loc=0x00, val=0xffff
[157567.781989] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x01, returns=0xffff
[157567.796985] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x01, returns=0xffff
[157567.811989] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x04, returns=0xffff
[157567.826974] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x05, returns=0xffff
[157567.841972] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x00, returns=0xffff
[157567.856974] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x01, returns=0xffff
[157567.871990] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x04, returns=0xffff
[157567.886974] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x05, returns=0xffff
[157567.906010] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x01, returns=0xffff
[157567.920986] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x01, returns=0xffff
[157567.935975] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x04, returns=0xffff
[157567.950974] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x05, returns=0xffff
[157567.965974] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x00, returns=0xffff
[157567.980970] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x01, returns=0xffff
[157567.995973] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x04, returns=0xffff
[157568.010971] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x05, returns=0xffff
[157568.025973] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x01, returns=0xffff
[157568.040969] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x01, returns=0xffff
[157568.055971] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x04, returns=0xffff
[157568.070970] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x05, returns=0xffff
[157568.085971] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x00, returns=0xffff
[157568.100971] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x01, returns=0xffff
[157568.115973] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x04, returns=0xffff
[157568.130970] dm9601 6-2:1.0 enp0s29f0u2: dm9601_mdio_read() phy_id=0x00, loc=0x05, returns=0xffff

So the problem is the same than in my uboot driver, the PHY always return 0xFFFF.

I have tried lots of hack but fail to bring the PHY up.

So it exsists two problem:
- Linux saying 100Mbps, full-duplex even if it is false.
- the PHY which seems in bad state.

For further information, the PHY is the internal one.
On the dongle, only the davicom chip is present (along with some resistors/capacitors and a quartz), so I think of the absence of an external PHY.

Regards

^ permalink raw reply

* Re: [PATCH] net/smc: common release code for non-accepted sockets
From: Karsten Graul @ 2019-06-27 13:16 UTC (permalink / raw)
  To: davem; +Cc: netdev, linux-s390, gor, heiko.carstens, raspl, ubraun
In-Reply-To: <20190627130452.15408-1-kgraul@linux.ibm.com>

Hi Dave,

I forgot to add that this patch is intended for the net-next tree.


On 27/06/2019 15:04, Karsten Graul wrote:
> From: Ursula Braun <ubraun@linux.ibm.com>
> 
> There are common steps when releasing an accepted or unaccepted socket.
> Move this code into a common routine.
> 
> Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
> Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
> ---
>  net/smc/af_smc.c | 73 +++++++++++++++++++++---------------------------
>  1 file changed, 32 insertions(+), 41 deletions(-)
> 
> diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
> index 7621ec2f539c..302e355f2ebc 100644
> --- a/net/smc/af_smc.c
> +++ b/net/smc/af_smc.c
> @@ -123,30 +123,11 @@ struct proto smc_proto6 = {
>  };
>  EXPORT_SYMBOL_GPL(smc_proto6);
>  
> -static int smc_release(struct socket *sock)
> +static int __smc_release(struct smc_sock *smc)
>  {
> -	struct sock *sk = sock->sk;
> -	struct smc_sock *smc;
> +	struct sock *sk = &smc->sk;
>  	int rc = 0;
>  
> -	if (!sk)
> -		goto out;
> -
> -	smc = smc_sk(sk);
> -
> -	/* cleanup for a dangling non-blocking connect */
> -	if (smc->connect_nonblock && sk->sk_state == SMC_INIT)
> -		tcp_abort(smc->clcsock->sk, ECONNABORTED);
> -	flush_work(&smc->connect_work);
> -
> -	if (sk->sk_state == SMC_LISTEN)
> -		/* smc_close_non_accepted() is called and acquires
> -		 * sock lock for child sockets again
> -		 */
> -		lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
> -	else
> -		lock_sock(sk);
> -
>  	if (!smc->use_fallback) {
>  		rc = smc_close_active(smc);
>  		sock_set_flag(sk, SOCK_DEAD);
> @@ -174,6 +155,35 @@ static int smc_release(struct socket *sock)
>  			smc_conn_free(&smc->conn);
>  	}
>  
> +	return rc;
> +}
> +
> +static int smc_release(struct socket *sock)
> +{
> +	struct sock *sk = sock->sk;
> +	struct smc_sock *smc;
> +	int rc = 0;
> +
> +	if (!sk)
> +		goto out;
> +
> +	smc = smc_sk(sk);
> +
> +	/* cleanup for a dangling non-blocking connect */
> +	if (smc->connect_nonblock && sk->sk_state == SMC_INIT)
> +		tcp_abort(smc->clcsock->sk, ECONNABORTED);
> +	flush_work(&smc->connect_work);
> +
> +	if (sk->sk_state == SMC_LISTEN)
> +		/* smc_close_non_accepted() is called and acquires
> +		 * sock lock for child sockets again
> +		 */
> +		lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
> +	else
> +		lock_sock(sk);
> +
> +	rc = __smc_release(smc);
> +
>  	/* detach socket */
>  	sock_orphan(sk);
>  	sock->sk = NULL;
> @@ -964,26 +974,7 @@ void smc_close_non_accepted(struct sock *sk)
>  	if (!sk->sk_lingertime)
>  		/* wait for peer closing */
>  		sk->sk_lingertime = SMC_MAX_STREAM_WAIT_TIMEOUT;
> -	if (!smc->use_fallback) {
> -		smc_close_active(smc);
> -		sock_set_flag(sk, SOCK_DEAD);
> -		sk->sk_shutdown |= SHUTDOWN_MASK;
> -	}
> -	sk->sk_prot->unhash(sk);
> -	if (smc->clcsock) {
> -		struct socket *tcp;
> -
> -		tcp = smc->clcsock;
> -		smc->clcsock = NULL;
> -		sock_release(tcp);
> -	}
> -	if (smc->use_fallback) {
> -		sock_put(sk); /* passive closing */
> -		sk->sk_state = SMC_CLOSED;
> -	} else {
> -		if (sk->sk_state == SMC_CLOSED)
> -			smc_conn_free(&smc->conn);
> -	}
> +	__smc_release(smc);
>  	release_sock(sk);
>  	sock_put(sk); /* final sock_put */
>  }
> 

-- 
Karsten

(I'm a dude!)


^ permalink raw reply

* Re: [PATCH] net: dsa: mv88e6xxx: wait after reset deactivation
From: Andrew Lunn @ 2019-06-27 13:13 UTC (permalink / raw)
  To: Baruch Siach; +Cc: Vivien Didelot, netdev
In-Reply-To: <92655572ed0c232b490967bed1245d121cc5a299.1561609786.git.baruch@tkos.co.il>

On Thu, Jun 27, 2019 at 07:29:46AM +0300, Baruch Siach wrote:
> Add a 1ms delay after reset deactivation. Otherwise the chip returns
> bogus ID value. This is observed with 88E6390 (Peridot) chip.
> 
> Signed-off-by: Baruch Siach <baruch@tkos.co.il>
> ---
>  drivers/net/dsa/mv88e6xxx/chip.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
> index f4e2db44ad91..549f528f216c 100644
> --- a/drivers/net/dsa/mv88e6xxx/chip.c
> +++ b/drivers/net/dsa/mv88e6xxx/chip.c
> @@ -4910,6 +4910,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
>  		err = PTR_ERR(chip->reset);
>  		goto out;
>  	}
> +	mdelay(1);
>  
>  	err = mv88e6xxx_detect(chip);
>  	if (err)

Hi Baruch

So your switch is held in reset by default, by the bootloader? So you
need to take it out of reset in order to detect it. Yes, this makes
sense.

However, please use usleep_range(10000, 20000), and only do this if
the GPIO is valid.

Thanks

	Andrew

^ permalink raw reply

* [PATCH 1/2 nf-next v2] netfilter: nft_meta: add NFT_META_BRI_O/IIFVPROTO support
From: wenxu @ 2019-06-27 13:07 UTC (permalink / raw)
  To: pablo, fw; +Cc: netfilter-devel, netdev

From: wenxu <wenxu@ucloud.cn>

This patch provide a meta to get the bridge vlan proto

nft add rule bridge firewall zones counter meta br_iifvproto 0x8100

Signed-off-by: wenxu <wenxu@ucloud.cn>
---
 include/uapi/linux/netfilter/nf_tables.h |  4 ++++
 net/netfilter/nft_meta.c                 | 18 ++++++++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 8859535..0f75a6d 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -796,6 +796,8 @@ enum nft_exthdr_attributes {
  * @NFT_META_IIFKIND: packet input interface kind name (dev->rtnl_link_ops->kind)
  * @NFT_META_OIFKIND: packet output interface kind name (dev->rtnl_link_ops->kind)
  * @NFT_META_BRI_PVID: packet input bridge port pvid
+ * @NFT_META_BRI_IIFVPROTO: packet input bridge port vlan proto
+ * @NFT_META_BRI_OIFVPROTO: packet output bridge port vlan proto
  */
 enum nft_meta_keys {
 	NFT_META_LEN,
@@ -827,6 +829,8 @@ enum nft_meta_keys {
 	NFT_META_IIFKIND,
 	NFT_META_OIFKIND,
 	NFT_META_BRI_PVID,
+	NFT_META_BRI_IIFVPROTO,
+	NFT_META_BRI_OIFVPROTO,
 };
 
 /**
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 4f8116d..e7e10fb 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -248,6 +248,22 @@ void nft_meta_get_eval(const struct nft_expr *expr,
 			return;
 		}
 		goto err;
+	case NFT_META_BRI_IIFVPROTO:
+		if (in == NULL || (p = br_port_get_rtnl_rcu(in)) == NULL)
+			goto err;
+		if (br_opt_get(p->br, BROPT_VLAN_ENABLED)) {
+			nft_reg_store16(dest, p->br->vlan_proto);
+			return;
+		}
+		goto err;
+	case NFT_META_BRI_OIFVPROTO:
+		if (out == NULL || (p = br_port_get_rtnl_rcu(out)) == NULL)
+			goto err;
+		if (br_opt_get(p->br, BROPT_VLAN_ENABLED)) {
+			nft_reg_store16(dest, p->br->vlan_proto);
+			return;
+		}
+		goto err;
 #endif
 	case NFT_META_IIFKIND:
 		if (in == NULL || in->rtnl_link_ops == NULL)
@@ -376,6 +392,8 @@ static int nft_meta_get_init(const struct nft_ctx *ctx,
 		len = IFNAMSIZ;
 		break;
 	case NFT_META_BRI_PVID:
+	case NFT_META_BRI_IIFVPROTO:
+	case NFT_META_BRI_OIFVPROTO:
 		if (ctx->family != NFPROTO_BRIDGE)
 			return -EOPNOTSUPP;
 		len = sizeof(u16);
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH 2/2 nf-next v2] netfilter:nft_meta: add NFT_META_VLAN support
From: wenxu @ 2019-06-27 13:07 UTC (permalink / raw)
  To: pablo, fw; +Cc: netfilter-devel, netdev
In-Reply-To: <1561640835-4507-1-git-send-email-wenxu@ucloud.cn>

From: wenxu <wenxu@ucloud.cn>

This patch provide a meta vlan to set the vlan tag of the packet.

for q-in-q vlan id 20:
meta vlan set 0x88a8:20

set the default 0x8100 vlan type with vlan id 20
meta vlan set 20

Signed-off-by: wenxu <wenxu@ucloud.cn>
---
 include/uapi/linux/netfilter/nf_tables.h |  4 ++++
 net/netfilter/nft_meta.c                 | 27 ++++++++++++++++++++++++++-
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 0f75a6d..acb8b75 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -798,6 +798,7 @@ enum nft_exthdr_attributes {
  * @NFT_META_BRI_PVID: packet input bridge port pvid
  * @NFT_META_BRI_IIFVPROTO: packet input bridge port vlan proto
  * @NFT_META_BRI_OIFVPROTO: packet output bridge port vlan proto
+ * @NFT_META_VLAN: packet vlan metadata
  */
 enum nft_meta_keys {
 	NFT_META_LEN,
@@ -831,6 +832,7 @@ enum nft_meta_keys {
 	NFT_META_BRI_PVID,
 	NFT_META_BRI_IIFVPROTO,
 	NFT_META_BRI_OIFVPROTO,
+	NFT_META_VLAN,
 };
 
 /**
@@ -897,12 +899,14 @@ enum nft_hash_attributes {
  * @NFTA_META_DREG: destination register (NLA_U32)
  * @NFTA_META_KEY: meta data item to load (NLA_U32: nft_meta_keys)
  * @NFTA_META_SREG: source register (NLA_U32)
+ * @NFTA_META_SREG2: source register (NLA_U32)
  */
 enum nft_meta_attributes {
 	NFTA_META_UNSPEC,
 	NFTA_META_DREG,
 	NFTA_META_KEY,
 	NFTA_META_SREG,
+	NFTA_META_SREG2,
 	__NFTA_META_MAX
 };
 #define NFTA_META_MAX		(__NFTA_META_MAX - 1)
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index e7e10fb..53f4547 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -28,7 +28,10 @@ struct nft_meta {
 	enum nft_meta_keys	key:8;
 	union {
 		enum nft_registers	dreg:8;
-		enum nft_registers	sreg:8;
+		struct {
+			enum nft_registers	sreg:8;
+			enum nft_registers	sreg2:8;
+		};
 	};
 };
 
@@ -320,6 +323,17 @@ static void nft_meta_set_eval(const struct nft_expr *expr,
 		skb->secmark = value;
 		break;
 #endif
+	case NFT_META_VLAN: {
+		u32 *sreg2 = &regs->data[meta->sreg2];
+		__be16 vlan_proto;
+		u16 vlan_tci;
+
+		vlan_tci = nft_reg_load16(sreg);
+		vlan_proto = nft_reg_load16(sreg2);
+
+		__vlan_hwaccel_put_tag(skb, vlan_proto, vlan_tci);
+		break;
+	}
 	default:
 		WARN_ON(1);
 	}
@@ -329,6 +343,7 @@ static void nft_meta_set_eval(const struct nft_expr *expr,
 	[NFTA_META_DREG]	= { .type = NLA_U32 },
 	[NFTA_META_KEY]		= { .type = NLA_U32 },
 	[NFTA_META_SREG]	= { .type = NLA_U32 },
+	[NFTA_META_SREG2]	= { .type = NLA_U32 },
 };
 
 static int nft_meta_get_init(const struct nft_ctx *ctx,
@@ -492,6 +507,13 @@ static int nft_meta_set_init(const struct nft_ctx *ctx,
 	case NFT_META_PKTTYPE:
 		len = sizeof(u8);
 		break;
+	case NFT_META_VLAN:
+		len = sizeof(u16);
+		priv->sreg2 = nft_parse_register(tb[NFTA_META_SREG2]);
+		err = nft_validate_register_load(priv->sreg2, len);
+		if (err < 0)
+			return err;
+		break;
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -530,6 +552,9 @@ static int nft_meta_set_dump(struct sk_buff *skb, const struct nft_expr *expr)
 		goto nla_put_failure;
 	if (nft_dump_register(skb, NFTA_META_SREG, priv->sreg))
 		goto nla_put_failure;
+	if (priv->key == NFT_META_VLAN &&
+	    nft_dump_register(skb, NFTA_META_SREG2, priv->sreg2))
+		goto nla_put_failure;
 
 	return 0;
 
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH] net/smc: common release code for non-accepted sockets
From: Karsten Graul @ 2019-06-27 13:04 UTC (permalink / raw)
  To: davem; +Cc: netdev, linux-s390, gor, heiko.carstens, raspl, ubraun

From: Ursula Braun <ubraun@linux.ibm.com>

There are common steps when releasing an accepted or unaccepted socket.
Move this code into a common routine.

Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
---
 net/smc/af_smc.c | 73 +++++++++++++++++++++---------------------------
 1 file changed, 32 insertions(+), 41 deletions(-)

diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index 7621ec2f539c..302e355f2ebc 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -123,30 +123,11 @@ struct proto smc_proto6 = {
 };
 EXPORT_SYMBOL_GPL(smc_proto6);
 
-static int smc_release(struct socket *sock)
+static int __smc_release(struct smc_sock *smc)
 {
-	struct sock *sk = sock->sk;
-	struct smc_sock *smc;
+	struct sock *sk = &smc->sk;
 	int rc = 0;
 
-	if (!sk)
-		goto out;
-
-	smc = smc_sk(sk);
-
-	/* cleanup for a dangling non-blocking connect */
-	if (smc->connect_nonblock && sk->sk_state == SMC_INIT)
-		tcp_abort(smc->clcsock->sk, ECONNABORTED);
-	flush_work(&smc->connect_work);
-
-	if (sk->sk_state == SMC_LISTEN)
-		/* smc_close_non_accepted() is called and acquires
-		 * sock lock for child sockets again
-		 */
-		lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
-	else
-		lock_sock(sk);
-
 	if (!smc->use_fallback) {
 		rc = smc_close_active(smc);
 		sock_set_flag(sk, SOCK_DEAD);
@@ -174,6 +155,35 @@ static int smc_release(struct socket *sock)
 			smc_conn_free(&smc->conn);
 	}
 
+	return rc;
+}
+
+static int smc_release(struct socket *sock)
+{
+	struct sock *sk = sock->sk;
+	struct smc_sock *smc;
+	int rc = 0;
+
+	if (!sk)
+		goto out;
+
+	smc = smc_sk(sk);
+
+	/* cleanup for a dangling non-blocking connect */
+	if (smc->connect_nonblock && sk->sk_state == SMC_INIT)
+		tcp_abort(smc->clcsock->sk, ECONNABORTED);
+	flush_work(&smc->connect_work);
+
+	if (sk->sk_state == SMC_LISTEN)
+		/* smc_close_non_accepted() is called and acquires
+		 * sock lock for child sockets again
+		 */
+		lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+	else
+		lock_sock(sk);
+
+	rc = __smc_release(smc);
+
 	/* detach socket */
 	sock_orphan(sk);
 	sock->sk = NULL;
@@ -964,26 +974,7 @@ void smc_close_non_accepted(struct sock *sk)
 	if (!sk->sk_lingertime)
 		/* wait for peer closing */
 		sk->sk_lingertime = SMC_MAX_STREAM_WAIT_TIMEOUT;
-	if (!smc->use_fallback) {
-		smc_close_active(smc);
-		sock_set_flag(sk, SOCK_DEAD);
-		sk->sk_shutdown |= SHUTDOWN_MASK;
-	}
-	sk->sk_prot->unhash(sk);
-	if (smc->clcsock) {
-		struct socket *tcp;
-
-		tcp = smc->clcsock;
-		smc->clcsock = NULL;
-		sock_release(tcp);
-	}
-	if (smc->use_fallback) {
-		sock_put(sk); /* passive closing */
-		sk->sk_state = SMC_CLOSED;
-	} else {
-		if (sk->sk_state == SMC_CLOSED)
-			smc_conn_free(&smc->conn);
-	}
+	__smc_release(smc);
 	release_sock(sk);
 	sock_put(sk); /* final sock_put */
 }
-- 
2.21.0


^ permalink raw reply related

* Re: [PATCH 2/3 nf-next] netfilter:nf_flow_table: Support bridge type flow offload
From: Pablo Neira Ayuso @ 2019-06-27 12:58 UTC (permalink / raw)
  To: wenxu; +Cc: Florian Westphal, netfilter-devel, netdev
In-Reply-To: <dce5cba2-766c-063e-745f-23b3dd83494b@ucloud.cn>

On Thu, Jun 27, 2019 at 02:22:36PM +0800, wenxu wrote:
> On 6/27/2019 3:19 AM, Florian Westphal wrote:
> > Florian Westphal <fw@strlen.de> wrote:
[...]
> >> Whats the idea with this patch?
> >>
> >> Do you see a performance improvement when bypassing bridge layer? If so,
> >> how much?
> >>
> >> I just wonder if its really cheaper than not using bridge conntrack in
> >> the first place :-)
> 
> This patch is based on the conntrack function in bridge.  It will
> bypass the fdb lookup and conntrack lookup to get the performance 
> improvement. The more important things for hardware offload in the
> future with nf_tables add hardware offload support

Florian would like to see numbers / benchmark.

^ permalink raw reply

* Re: [PATCH 2/2 nf-next] netfilter:nft_meta: add NFT_META_VLAN support
From: Pablo Neira Ayuso @ 2019-06-27 12:35 UTC (permalink / raw)
  To: wenxu; +Cc: fw, netfilter-devel, netdev
In-Reply-To: <1561601357-20486-2-git-send-email-wenxu@ucloud.cn>

On Thu, Jun 27, 2019 at 10:09:17AM +0800, wenxu@ucloud.cn wrote:
> From: wenxu <wenxu@ucloud.cn>
> 
> This patch provide a meta vlan to set the vlan tag of the packet.
> 
> for q-in-q vlan id 20:
> meta vlan set 0x88a8:20

Actually, I think this is not very useful for stacked vlan since this
just sets/mangles the existing meta vlan data.

We'll need infrastructure that uses skb_vlan_push() and _pop().

Patch looks good anyway, such infrastructure to push/pop can be added
later on.

Thanks.

> set the default 0x8100 vlan type with vlan id 20
> meta vlan set 20
> 
> Signed-off-by: wenxu <wenxu@ucloud.cn>
> ---
>  include/uapi/linux/netfilter/nf_tables.h |  4 ++++
>  net/netfilter/nft_meta.c                 | 27 ++++++++++++++++++++++++++-
>  2 files changed, 30 insertions(+), 1 deletion(-)
> 
> diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
> index 0b18646..cf037f2 100644
> --- a/include/uapi/linux/netfilter/nf_tables.h
> +++ b/include/uapi/linux/netfilter/nf_tables.h
> @@ -797,6 +797,7 @@ enum nft_exthdr_attributes {
>   * @NFT_META_OIFKIND: packet output interface kind name (dev->rtnl_link_ops->kind)
>   * @NFT_META_BRI_PVID: packet input bridge port pvid
>   * @NFT_META_BRI_VLAN_PROTO: packet input bridge vlan proto
> + * @NFT_META_VLAN: packet vlan metadata
>   */
>  enum nft_meta_keys {
>  	NFT_META_LEN,
> @@ -829,6 +830,7 @@ enum nft_meta_keys {
>  	NFT_META_OIFKIND,
>  	NFT_META_BRI_PVID,
>  	NFT_META_BRI_VLAN_PROTO,
> +	NFT_META_VLAN,
>  };
>  
>  /**
> @@ -895,12 +897,14 @@ enum nft_hash_attributes {
>   * @NFTA_META_DREG: destination register (NLA_U32)
>   * @NFTA_META_KEY: meta data item to load (NLA_U32: nft_meta_keys)
>   * @NFTA_META_SREG: source register (NLA_U32)
> + * @NFTA_META_SREG2: source register (NLA_U32)
>   */
>  enum nft_meta_attributes {
>  	NFTA_META_UNSPEC,
>  	NFTA_META_DREG,
>  	NFTA_META_KEY,
>  	NFTA_META_SREG,
> +	NFTA_META_SREG2,
>  	__NFTA_META_MAX
>  };
>  #define NFTA_META_MAX		(__NFTA_META_MAX - 1)
> diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
> index e3adf6a..29a6679 100644
> --- a/net/netfilter/nft_meta.c
> +++ b/net/netfilter/nft_meta.c
> @@ -28,7 +28,10 @@ struct nft_meta {
>  	enum nft_meta_keys	key:8;
>  	union {
>  		enum nft_registers	dreg:8;
> -		enum nft_registers	sreg:8;
> +		struct {
> +			enum nft_registers	sreg:8;
> +			enum nft_registers	sreg2:8;
> +		};
>  	};
>  };
>  
> @@ -312,6 +315,17 @@ static void nft_meta_set_eval(const struct nft_expr *expr,
>  		skb->secmark = value;
>  		break;
>  #endif
> +	case NFT_META_VLAN: {
> +		u32 *sreg2 = &regs->data[meta->sreg2];
> +		__be16 vlan_proto;
> +		u16 vlan_tci;
> +
> +		vlan_tci = nft_reg_load16(sreg);
> +		vlan_proto = nft_reg_load16(sreg2);
> +
> +		__vlan_hwaccel_put_tag(skb, vlan_proto, vlan_tci);
> +		break;
> +	}
>  	default:
>  		WARN_ON(1);
>  	}
> @@ -321,6 +335,7 @@ static void nft_meta_set_eval(const struct nft_expr *expr,
>  	[NFTA_META_DREG]	= { .type = NLA_U32 },
>  	[NFTA_META_KEY]		= { .type = NLA_U32 },
>  	[NFTA_META_SREG]	= { .type = NLA_U32 },
> +	[NFTA_META_SREG2]	= { .type = NLA_U32 },
>  };
>  
>  static int nft_meta_get_init(const struct nft_ctx *ctx,
> @@ -483,6 +498,13 @@ static int nft_meta_set_init(const struct nft_ctx *ctx,
>  	case NFT_META_PKTTYPE:
>  		len = sizeof(u8);
>  		break;
> +	case NFT_META_VLAN:
> +		len = sizeof(u16);
> +		priv->sreg2 = nft_parse_register(tb[NFTA_META_SREG2]);
> +		err = nft_validate_register_load(priv->sreg2, len);
> +		if (err < 0)
> +			return err;
> +		break;
>  	default:
>  		return -EOPNOTSUPP;
>  	}
> @@ -521,6 +543,9 @@ static int nft_meta_set_dump(struct sk_buff *skb, const struct nft_expr *expr)
>  		goto nla_put_failure;
>  	if (nft_dump_register(skb, NFTA_META_SREG, priv->sreg))
>  		goto nla_put_failure;
> +	if (priv->key == NFT_META_VLAN &&
> +	    nft_dump_register(skb, NFTA_META_SREG2, priv->sreg2))
> +		goto nla_put_failure;
>  
>  	return 0;
>  
> -- 
> 1.8.3.1
> 

^ permalink raw reply

* Re: [RFC, PATCH 2/2, net-next] net: netsec: add XDP support
From: Ilias Apalodimas @ 2019-06-27 12:24 UTC (permalink / raw)
  To: Jesper Dangaard Brouer
  Cc: netdev, jaswinder.singh, ard.biesheuvel, bjorn.topel,
	magnus.karlsson, daniel, ast, makita.toshiaki, jakub.kicinski,
	john.fastabend, davem
In-Reply-To: <20190627142305.16b8f331@carbon>

On Thu, Jun 27, 2019 at 02:23:05PM +0200, Jesper Dangaard Brouer wrote:
> On Tue, 25 Jun 2019 18:06:19 +0300
> Ilias Apalodimas <ilias.apalodimas@linaro.org> wrote:
> 
> > @@ -609,6 +639,9 @@ static bool netsec_clean_tx_dring(struct netsec_priv *priv)
> >  	int tail = dring->tail;
> >  	int cnt = 0;
> >  
> > +	if (dring->is_xdp)
> > +		spin_lock(&dring->lock);
> > +
> >  	pkts = 0;
> >  	bytes = 0;
> >  	entry = dring->vaddr + DESC_SZ * tail;
> > @@ -622,16 +655,24 @@ static bool netsec_clean_tx_dring(struct netsec_priv *priv)
> >  		eop = (entry->attr >> NETSEC_TX_LAST) & 1;
> >  		dma_rmb();
> >  
> > -		dma_unmap_single(priv->dev, desc->dma_addr, desc->len,
> > -				 DMA_TO_DEVICE);
> > -		if (eop) {
> > -			pkts++;
> > +		if (!eop)
> > +			goto next;
> > +
> > +		if (desc->buf_type == TYPE_NETSEC_SKB) {
> > +			dma_unmap_single(priv->dev, desc->dma_addr, desc->len,
> > +					 DMA_TO_DEVICE);
> 
> I don't think this is correct.  If I read the code correctly, you will
> miss the DMA unmap for !eop packets.
> 

You are reading it correct, thanks for catching this.
I'll fix it on the proper patch

Thanks
/Ilias

^ permalink raw reply

* Re: [RFC, PATCH 2/2, net-next] net: netsec: add XDP support
From: Jesper Dangaard Brouer @ 2019-06-27 12:23 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: netdev, jaswinder.singh, ard.biesheuvel, bjorn.topel,
	magnus.karlsson, daniel, ast, makita.toshiaki, jakub.kicinski,
	john.fastabend, davem, brouer
In-Reply-To: <1561475179-7686-3-git-send-email-ilias.apalodimas@linaro.org>

On Tue, 25 Jun 2019 18:06:19 +0300
Ilias Apalodimas <ilias.apalodimas@linaro.org> wrote:

> @@ -609,6 +639,9 @@ static bool netsec_clean_tx_dring(struct netsec_priv *priv)
>  	int tail = dring->tail;
>  	int cnt = 0;
>  
> +	if (dring->is_xdp)
> +		spin_lock(&dring->lock);
> +
>  	pkts = 0;
>  	bytes = 0;
>  	entry = dring->vaddr + DESC_SZ * tail;
> @@ -622,16 +655,24 @@ static bool netsec_clean_tx_dring(struct netsec_priv *priv)
>  		eop = (entry->attr >> NETSEC_TX_LAST) & 1;
>  		dma_rmb();
>  
> -		dma_unmap_single(priv->dev, desc->dma_addr, desc->len,
> -				 DMA_TO_DEVICE);
> -		if (eop) {
> -			pkts++;
> +		if (!eop)
> +			goto next;
> +
> +		if (desc->buf_type == TYPE_NETSEC_SKB) {
> +			dma_unmap_single(priv->dev, desc->dma_addr, desc->len,
> +					 DMA_TO_DEVICE);

I don't think this is correct.  If I read the code correctly, you will
miss the DMA unmap for !eop packets.

>  			bytes += desc->skb->len;
>  			dev_kfree_skb(desc->skb);
> +		} else {
> +			if (desc->buf_type == TYPE_NETSEC_XDP_NDO)
> +				dma_unmap_single(priv->dev, desc->dma_addr,
> +						 desc->len, DMA_TO_DEVICE);
> +			xdp_return_frame(desc->xdpf);
>  		}
>  		/* clean up so netsec_uninit_pkt_dring() won't free the skb
>  		 * again
>  		 */
> +next:
>  		*desc = (struct netsec_desc){};
>  
>  		/* entry->attr is not going to be accessed by the NIC until
> @@ -645,6 +686,8 @@ static bool netsec_clean_tx_dring(struct netsec_priv *priv)
>  		entry = dring->vaddr + DESC_SZ * tail;
>  		cnt++;
>  	}
> +	if (dring->is_xdp)
> +		spin_unlock(&dring->lock);
>  
>  	if (!cnt)
>  		return false;



-- 
Best regards,
  Jesper Dangaard Brouer
  MSc.CS, Principal Kernel Engineer at Red Hat
  LinkedIn: http://www.linkedin.com/in/brouer

^ permalink raw reply

* RE: [RFC net-next 1/5] net: stmmac: introduce IEEE 802.1Qbv configuration functionalities
From: Jose Abreu @ 2019-06-27 12:21 UTC (permalink / raw)
  To: Voon Weifeng, David S. Miller, Maxime Coquelin
  Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	Giuseppe Cavallaro, Andrew Lunn, Florian Fainelli,
	Alexandre Torgue, Vinicius Costa Gomes, Ong Boon Leong
In-Reply-To: <1560893778-6838-2-git-send-email-weifeng.voon@intel.com>

From: Voon Weifeng <weifeng.voon@intel.com>

> diff --git a/drivers/net/ethernet/stmicro/stmmac/dw_tsn_lib.c b/drivers/net/ethernet/stmicro/stmmac/dw_tsn_lib.c
> new file mode 100644
> index 000000000000..cba27c604cb1
> --- /dev/null
> +++ b/drivers/net/ethernet/stmicro/stmmac/dw_tsn_lib.c

XGMAC also supports TSN features so I think more abstraction is needed 
on this because the XGMAC implementation is very similar (only reg 
offsets and bitfields changes).

I would rather:
	- Implement HW specific handling in dwmac4_core.c / dwmac4_dma.c and 
add the callbacks in hwif table;
	- Let TSN logic in this file but call it stmmac_tsn.c.

> @@ -3621,6 +3622,8 @@ static int stmmac_set_features(struct net_device *netdev,
>  	 */
>  	stmmac_rx_ipc(priv, priv->hw);
>  
> +	netdev->features = features;

Isn't this a fix ?

^ 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