Netdev List
 help / color / mirror / Atom feed
* [net-next 07/12] net/mlx5e: Tx, Soften inline mode VLAN dependencies
From: Saeed Mahameed @ 2019-08-01 19:57 UTC (permalink / raw)
  To: David S. Miller
  Cc: netdev@vger.kernel.org, Tariq Toukan, Noam Stolero,
	Saeed Mahameed
In-Reply-To: <20190801195620.26180-1-saeedm@mellanox.com>

From: Tariq Toukan <tariqt@mellanox.com>

If capable, use zero inline mode in TX WQE for non-VLAN packets.
For VLAN ones, keep the enforcement of at least L2 inline mode,
unless the WQE VLAN insertion offload cap is on.

Performance:
Tested single core packet rate of 64Bytes.

NIC: ConnectX-5
CPU: Intel(R) Xeon(R) Gold 6154 CPU @ 3.00GHz

pktgen:
Before: 12.46 Mpps
After:  14.65 Mpps (+17.5%)

XDP_TX:
The MPWQE flow is not affected, as it already has this optimization.
So we test with priv-flag xdp_tx_mpwqe: off.

Before:  9.90 Mpps
After:  10.20 Mpps (+3%)

Signed-off-by: Tariq Toukan <tariqt@mellanox.com>
Tested-by: Noam Stolero <noams@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlx5/core/en.h  |  2 +-
 .../net/ethernet/mellanox/mlx5/core/en/txrx.h | 22 +++++++++++++++++--
 .../ethernet/mellanox/mlx5/core/en_common.c   | 12 ----------
 .../ethernet/mellanox/mlx5/core/en_dcbnl.c    |  2 +-
 .../net/ethernet/mellanox/mlx5/core/en_main.c |  4 +++-
 .../net/ethernet/mellanox/mlx5/core/en_tx.c   |  7 +++---
 .../net/ethernet/mellanox/mlx5/core/vport.c   |  7 +++---
 7 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 745bcc25c6f8..30f13f81c965 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -359,6 +359,7 @@ enum {
 	MLX5E_SQ_STATE_IPSEC,
 	MLX5E_SQ_STATE_AM,
 	MLX5E_SQ_STATE_TLS,
+	MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE,
 };
 
 struct mlx5e_sq_wqe_info {
@@ -1132,7 +1133,6 @@ void mlx5e_build_rq_params(struct mlx5_core_dev *mdev,
 			   struct mlx5e_params *params);
 void mlx5e_build_rss_params(struct mlx5e_rss_params *rss_params,
 			    u16 num_channels);
-u8 mlx5e_params_calculate_tx_min_inline(struct mlx5_core_dev *mdev);
 void mlx5e_rx_dim_work(struct work_struct *work);
 void mlx5e_tx_dim_work(struct work_struct *work);
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h
index 7da22b413a48..87be96747902 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h
@@ -117,9 +117,27 @@ mlx5e_notify_hw(struct mlx5_wq_cyc *wq, u16 pc, void __iomem *uar_map,
 	mlx5_write64((__be32 *)ctrl, uar_map);
 }
 
-static inline bool mlx5e_transport_inline_tx_wqe(struct mlx5e_tx_wqe *wqe)
+static inline bool mlx5e_transport_inline_tx_wqe(struct mlx5_wqe_ctrl_seg *cseg)
 {
-	return !!wqe->ctrl.tisn;
+	return cseg && !!cseg->tisn;
+}
+
+static inline u8
+mlx5e_tx_wqe_inline_mode(struct mlx5e_txqsq *sq, struct mlx5_wqe_ctrl_seg *cseg,
+			 struct sk_buff *skb)
+{
+	u8 mode;
+
+	if (mlx5e_transport_inline_tx_wqe(cseg))
+		return MLX5_INLINE_MODE_TCP_UDP;
+
+	mode = sq->min_inline_mode;
+
+	if (skb_vlan_tag_present(skb) &&
+	    test_bit(MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE, &sq->state))
+		mode = max_t(u8, MLX5_INLINE_MODE_L2, mode);
+
+	return mode;
 }
 
 static inline void mlx5e_cq_arm(struct mlx5e_cq *cq)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c
index 1539cf3de5dc..f7890e0ce96c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c
@@ -180,15 +180,3 @@ int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb)
 
 	return err;
 }
-
-u8 mlx5e_params_calculate_tx_min_inline(struct mlx5_core_dev *mdev)
-{
-	u8 min_inline_mode;
-
-	mlx5_query_min_inline(mdev, &min_inline_mode);
-	if (min_inline_mode == MLX5_INLINE_MODE_NONE &&
-	    !MLX5_CAP_ETH(mdev, wqe_vlan_insert))
-		min_inline_mode = MLX5_INLINE_MODE_L2;
-
-	return min_inline_mode;
-}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
index 8dd31b5c740c..01f2918063af 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
@@ -1101,7 +1101,7 @@ void mlx5e_dcbnl_delete_app(struct mlx5e_priv *priv)
 static void mlx5e_trust_update_tx_min_inline_mode(struct mlx5e_priv *priv,
 						  struct mlx5e_params *params)
 {
-	params->tx_min_inline_mode = mlx5e_params_calculate_tx_min_inline(priv->mdev);
+	mlx5_query_min_inline(priv->mdev, &params->tx_min_inline_mode);
 	if (priv->dcbx_dp.trust_state == MLX5_QPTS_TRUST_DSCP &&
 	    params->tx_min_inline_mode == MLX5_INLINE_MODE_L2)
 		params->tx_min_inline_mode = MLX5_INLINE_MODE_IP;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index b2618dd6dd10..e75cb18c2256 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -1131,6 +1131,8 @@ static int mlx5e_alloc_txqsq(struct mlx5e_channel *c,
 	sq->stats     = &c->priv->channel_stats[c->ix].sq[tc];
 	sq->stop_room = MLX5E_SQ_STOP_ROOM;
 	INIT_WORK(&sq->recover_work, mlx5e_tx_err_cqe_work);
+	if (!MLX5_CAP_ETH(mdev, wqe_vlan_insert))
+		set_bit(MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE, &sq->state);
 	if (MLX5_IPSEC_DEV(c->priv->mdev))
 		set_bit(MLX5E_SQ_STATE_IPSEC, &sq->state);
 	if (mlx5_accel_is_tls_device(c->priv->mdev)) {
@@ -4777,7 +4779,7 @@ void mlx5e_build_nic_params(struct mlx5_core_dev *mdev,
 	mlx5e_set_tx_cq_mode_params(params, MLX5_CQ_PERIOD_MODE_START_FROM_EQE);
 
 	/* TX inline */
-	params->tx_min_inline_mode = mlx5e_params_calculate_tx_min_inline(mdev);
+	mlx5_query_min_inline(mdev, &params->tx_min_inline_mode);
 
 	/* RSS */
 	mlx5e_build_rss_params(rss_params, params->num_channels);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
index acf25cc38fa1..d3a67a9b4eba 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
@@ -292,8 +292,7 @@ netdev_tx_t mlx5e_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb,
 		num_bytes = skb->len + (skb_shinfo(skb)->gso_segs - 1) * ihs;
 		stats->packets += skb_shinfo(skb)->gso_segs;
 	} else {
-		u8 mode = mlx5e_transport_inline_tx_wqe(wqe) ?
-			MLX5_INLINE_MODE_TCP_UDP : sq->min_inline_mode;
+		u8 mode = mlx5e_tx_wqe_inline_mode(sq, &wqe->ctrl, skb);
 
 		opcode    = MLX5_OPCODE_SEND;
 		mss       = 0;
@@ -608,9 +607,11 @@ netdev_tx_t mlx5i_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb,
 		num_bytes = skb->len + (skb_shinfo(skb)->gso_segs - 1) * ihs;
 		stats->packets += skb_shinfo(skb)->gso_segs;
 	} else {
+		u8 mode = mlx5e_tx_wqe_inline_mode(sq, NULL, skb);
+
 		opcode    = MLX5_OPCODE_SEND;
 		mss       = 0;
-		ihs       = mlx5e_calc_min_inline(sq->min_inline_mode, skb);
+		ihs       = mlx5e_calc_min_inline(mode, skb);
 		num_bytes = max_t(unsigned int, skb->len, ETH_ZLEN);
 		stats->packets++;
 	}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
index c912d82ca64b..30f7848a6f88 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
@@ -122,12 +122,13 @@ void mlx5_query_min_inline(struct mlx5_core_dev *mdev,
 			   u8 *min_inline_mode)
 {
 	switch (MLX5_CAP_ETH(mdev, wqe_inline_mode)) {
+	case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT:
+		if (!mlx5_query_nic_vport_min_inline(mdev, 0, min_inline_mode))
+			break;
+		/* fall through */
 	case MLX5_CAP_INLINE_MODE_L2:
 		*min_inline_mode = MLX5_INLINE_MODE_L2;
 		break;
-	case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT:
-		mlx5_query_nic_vport_min_inline(mdev, 0, min_inline_mode);
-		break;
 	case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
 		*min_inline_mode = MLX5_INLINE_MODE_NONE;
 		break;
-- 
2.21.0


^ permalink raw reply related

* [net-next 05/12] net/mlx5e: XDP, Close TX MPWQE session when no room for inline packet left
From: Saeed Mahameed @ 2019-08-01 19:56 UTC (permalink / raw)
  To: David S. Miller
  Cc: netdev@vger.kernel.org, Shay Agroskin, Tariq Toukan,
	Saeed Mahameed
In-Reply-To: <20190801195620.26180-1-saeedm@mellanox.com>

From: Shay Agroskin <shayag@mellanox.com>

In MPWQE mode, when transmitting packets with XDP, a packet that is smaller
than a certain size (set to 256 bytes) would be sent inline within its WQE
TX descriptor (mem-copied), in case the hardware tx queue is congested
beyond a pre-defined water-mark.

If a MPWQE cannot contain an additional inline packet, we close this
MPWQE session, and send the packet inlined within the next MPWQE.
To save some MPWQE session close+open operations, we don't open MPWQE
sessions that are contiguously smaller than certain size (set to the
HW MPWQE maximum size). If there isn't enough contiguous room in the
send queue, we fill it with NOPs and wrap the send queue index around.

This way, qualified packets are always sent inline.

Perf tests:
Tested packet rate for UDP 64Byte multi-stream
over two dual port ConnectX-5 100Gbps NICs.
CPU: Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz

XDP_TX:

With 24 channels:
| ------ | bounced packets | inlined packets | inline ratio |
| before | 113.6Mpps       | 96.3Mpps        | 84%          |
| after  |   115Mpps       | 99.5Mpps        | 86%          |

With one channel:

| ------ | bounced packets | inlined packets | inline ratio |
| before | 6.7Mpps         | 0pps            | 0%           |
| after  | 6.8Mpps         | 0pps            | 0%           |

As we can see, there is improvement in both inline ratio and overall
packet rate for 24 channels. Also, we see no degradation for the
one-channel case.

Signed-off-by: Shay Agroskin <shayag@mellanox.com>
Signed-off-by: Tariq Toukan <tariqt@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlx5/core/en.h  |  2 -
 .../net/ethernet/mellanox/mlx5/core/en/xdp.c  | 32 ++++-------
 .../net/ethernet/mellanox/mlx5/core/en/xdp.h  | 53 +++++++++++++++----
 .../ethernet/mellanox/mlx5/core/en_stats.c    |  6 +++
 .../ethernet/mellanox/mlx5/core/en_stats.h    |  3 ++
 5 files changed, 63 insertions(+), 33 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 79d93d6c7d7a..745bcc25c6f8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -483,8 +483,6 @@ struct mlx5e_xdp_mpwqe {
 	struct mlx5e_tx_wqe *wqe;
 	u8                   ds_count;
 	u8                   pkt_count;
-	u8                   max_ds_count;
-	u8                   complete;
 	u8                   inline_on;
 };
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
index b0b982cf69bb..8cb98326531f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
@@ -179,34 +179,22 @@ static void mlx5e_xdp_mpwqe_session_start(struct mlx5e_xdpsq *sq)
 	struct mlx5e_xdp_mpwqe *session = &sq->mpwqe;
 	struct mlx5e_xdpsq_stats *stats = sq->stats;
 	struct mlx5_wq_cyc *wq = &sq->wq;
-	u8  wqebbs;
-	u16 pi;
+	u16 pi, contig_wqebbs;
+
+	pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc);
+	contig_wqebbs = mlx5_wq_cyc_get_contig_wqebbs(wq, pi);
+
+	if (unlikely(contig_wqebbs < MLX5_SEND_WQE_MAX_WQEBBS))
+		mlx5e_fill_xdpsq_frag_edge(sq, wq, pi, contig_wqebbs);
 
 	mlx5e_xdpsq_fetch_wqe(sq, &session->wqe);
 
 	prefetchw(session->wqe->data);
 	session->ds_count  = MLX5E_XDP_TX_EMPTY_DS_COUNT;
 	session->pkt_count = 0;
-	session->complete  = 0;
 
 	pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc);
 
-/* The mult of MLX5_SEND_WQE_MAX_WQEBBS * MLX5_SEND_WQEBB_NUM_DS
- * (16 * 4 == 64) does not fit in the 6-bit DS field of Ctrl Segment.
- * We use a bound lower that MLX5_SEND_WQE_MAX_WQEBBS to let a
- * full-session WQE be cache-aligned.
- */
-#if L1_CACHE_BYTES < 128
-#define MLX5E_XDP_MPW_MAX_WQEBBS (MLX5_SEND_WQE_MAX_WQEBBS - 1)
-#else
-#define MLX5E_XDP_MPW_MAX_WQEBBS (MLX5_SEND_WQE_MAX_WQEBBS - 2)
-#endif
-
-	wqebbs = min_t(u16, mlx5_wq_cyc_get_contig_wqebbs(wq, pi),
-		       MLX5E_XDP_MPW_MAX_WQEBBS);
-
-	session->max_ds_count = MLX5_SEND_WQEBB_NUM_DS * wqebbs;
-
 	mlx5e_xdp_update_inline_state(sq);
 
 	stats->mpwqe++;
@@ -244,7 +232,7 @@ static int mlx5e_xmit_xdp_frame_check_mpwqe(struct mlx5e_xdpsq *sq)
 {
 	if (unlikely(!sq->mpwqe.wqe)) {
 		if (unlikely(!mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc,
-						     MLX5_SEND_WQE_MAX_WQEBBS))) {
+						     MLX5E_XDPSQ_STOP_ROOM))) {
 			/* SQ is full, ring doorbell */
 			mlx5e_xmit_xdp_doorbell(sq);
 			sq->stats->full++;
@@ -285,8 +273,8 @@ static bool mlx5e_xmit_xdp_frame_mpwqe(struct mlx5e_xdpsq *sq,
 
 	mlx5e_xdp_mpwqe_add_dseg(sq, xdptxd, stats);
 
-	if (unlikely(session->complete ||
-		     session->ds_count == session->max_ds_count))
+	if (unlikely(mlx5e_xdp_no_room_for_inline_pkt(session) ||
+		     session->ds_count == MLX5E_XDP_MPW_MAX_NUM_DS))
 		mlx5e_xdp_mpwqe_complete(sq);
 
 	mlx5e_xdpi_fifo_push(&sq->db.xdpi_fifo, xdpi);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
index b90923932668..e0ed7710f5f1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
@@ -40,6 +40,26 @@
 	(sizeof(struct mlx5e_tx_wqe) / MLX5_SEND_WQE_DS)
 #define MLX5E_XDP_TX_DS_COUNT (MLX5E_XDP_TX_EMPTY_DS_COUNT + 1 /* SG DS */)
 
+#define MLX5E_XDPSQ_STOP_ROOM (MLX5E_SQ_STOP_ROOM)
+
+#define MLX5E_XDP_INLINE_WQE_SZ_THRSD (256 - sizeof(struct mlx5_wqe_inline_seg))
+#define MLX5E_XDP_INLINE_WQE_MAX_DS_CNT \
+	DIV_ROUND_UP(MLX5E_XDP_INLINE_WQE_SZ_THRSD, MLX5_SEND_WQE_DS)
+
+/* The mult of MLX5_SEND_WQE_MAX_WQEBBS * MLX5_SEND_WQEBB_NUM_DS
+ * (16 * 4 == 64) does not fit in the 6-bit DS field of Ctrl Segment.
+ * We use a bound lower that MLX5_SEND_WQE_MAX_WQEBBS to let a
+ * full-session WQE be cache-aligned.
+ */
+#if L1_CACHE_BYTES < 128
+#define MLX5E_XDP_MPW_MAX_WQEBBS (MLX5_SEND_WQE_MAX_WQEBBS - 1)
+#else
+#define MLX5E_XDP_MPW_MAX_WQEBBS (MLX5_SEND_WQE_MAX_WQEBBS - 2)
+#endif
+
+#define MLX5E_XDP_MPW_MAX_NUM_DS \
+	(MLX5E_XDP_MPW_MAX_WQEBBS * MLX5_SEND_WQEBB_NUM_DS)
+
 struct mlx5e_xsk_param;
 int mlx5e_xdp_max_mtu(struct mlx5e_params *params, struct mlx5e_xsk_param *xsk);
 bool mlx5e_xdp_handle(struct mlx5e_rq *rq, struct mlx5e_dma_info *di,
@@ -114,6 +134,30 @@ static inline void mlx5e_xdp_update_inline_state(struct mlx5e_xdpsq *sq)
 		session->inline_on = 1;
 }
 
+static inline bool
+mlx5e_xdp_no_room_for_inline_pkt(struct mlx5e_xdp_mpwqe *session)
+{
+	return session->inline_on &&
+	       session->ds_count + MLX5E_XDP_INLINE_WQE_MAX_DS_CNT > MLX5E_XDP_MPW_MAX_NUM_DS;
+}
+
+static inline void
+mlx5e_fill_xdpsq_frag_edge(struct mlx5e_xdpsq *sq, struct mlx5_wq_cyc *wq,
+			   u16 pi, u16 nnops)
+{
+	struct mlx5e_xdp_wqe_info *edge_wi, *wi = &sq->db.wqe_info[pi];
+
+	edge_wi = wi + nnops;
+	/* fill sq frag edge with nops to avoid wqe wrapping two pages */
+	for (; wi < edge_wi; wi++) {
+		wi->num_wqebbs = 1;
+		wi->num_pkts   = 0;
+		mlx5e_post_nop(wq, sq->sqn, &sq->pc);
+	}
+
+	sq->stats->nops += nnops;
+}
+
 static inline void
 mlx5e_xdp_mpwqe_add_dseg(struct mlx5e_xdpsq *sq,
 			 struct mlx5e_xdp_xmit_data *xdptxd,
@@ -126,20 +170,12 @@ mlx5e_xdp_mpwqe_add_dseg(struct mlx5e_xdpsq *sq,
 
 	session->pkt_count++;
 
-#define MLX5E_XDP_INLINE_WQE_SZ_THRSD (256 - sizeof(struct mlx5_wqe_inline_seg))
-
 	if (session->inline_on && dma_len <= MLX5E_XDP_INLINE_WQE_SZ_THRSD) {
 		struct mlx5_wqe_inline_seg *inline_dseg =
 			(struct mlx5_wqe_inline_seg *)dseg;
 		u16 ds_len = sizeof(*inline_dseg) + dma_len;
 		u16 ds_cnt = DIV_ROUND_UP(ds_len, MLX5_SEND_WQE_DS);
 
-		if (unlikely(session->ds_count + ds_cnt > session->max_ds_count)) {
-			/* Not enough space for inline wqe, send with memory pointer */
-			session->complete = true;
-			goto no_inline;
-		}
-
 		inline_dseg->byte_count = cpu_to_be32(dma_len | MLX5_INLINE_SEG);
 		memcpy(inline_dseg->data, xdptxd->data, dma_len);
 
@@ -148,7 +184,6 @@ mlx5e_xdp_mpwqe_add_dseg(struct mlx5e_xdpsq *sq,
 		return;
 	}
 
-no_inline:
 	dseg->addr       = cpu_to_be64(xdptxd->dma_addr);
 	dseg->byte_count = cpu_to_be32(dma_len);
 	dseg->lkey       = sq->mkey_be;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
index 539b4d3656da..6eee3c7d4b06 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
@@ -74,6 +74,7 @@ static const struct counter_desc sw_stats_desc[] = {
 	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx_xmit) },
 	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx_mpwqe) },
 	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx_inlnw) },
+	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx_nops) },
 	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx_full) },
 	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx_err) },
 	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx_cqe) },
@@ -90,6 +91,7 @@ static const struct counter_desc sw_stats_desc[] = {
 	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_xdp_xmit) },
 	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_xdp_mpwqe) },
 	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_xdp_inlnw) },
+	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_xdp_nops) },
 	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_xdp_full) },
 	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_xdp_err) },
 	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_xdp_cqes) },
@@ -200,6 +202,7 @@ static void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv)
 		s->rx_xdp_tx_xmit  += xdpsq_stats->xmit;
 		s->rx_xdp_tx_mpwqe += xdpsq_stats->mpwqe;
 		s->rx_xdp_tx_inlnw += xdpsq_stats->inlnw;
+		s->rx_xdp_tx_nops  += xdpsq_stats->nops;
 		s->rx_xdp_tx_full  += xdpsq_stats->full;
 		s->rx_xdp_tx_err   += xdpsq_stats->err;
 		s->rx_xdp_tx_cqe   += xdpsq_stats->cqes;
@@ -227,6 +230,7 @@ static void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv)
 		s->tx_xdp_xmit    += xdpsq_red_stats->xmit;
 		s->tx_xdp_mpwqe   += xdpsq_red_stats->mpwqe;
 		s->tx_xdp_inlnw   += xdpsq_red_stats->inlnw;
+		s->tx_xdp_nops	  += xdpsq_red_stats->nops;
 		s->tx_xdp_full    += xdpsq_red_stats->full;
 		s->tx_xdp_err     += xdpsq_red_stats->err;
 		s->tx_xdp_cqes    += xdpsq_red_stats->cqes;
@@ -1331,6 +1335,7 @@ static const struct counter_desc rq_xdpsq_stats_desc[] = {
 	{ MLX5E_DECLARE_RQ_XDPSQ_STAT(struct mlx5e_xdpsq_stats, xmit) },
 	{ MLX5E_DECLARE_RQ_XDPSQ_STAT(struct mlx5e_xdpsq_stats, mpwqe) },
 	{ MLX5E_DECLARE_RQ_XDPSQ_STAT(struct mlx5e_xdpsq_stats, inlnw) },
+	{ MLX5E_DECLARE_RQ_XDPSQ_STAT(struct mlx5e_xdpsq_stats, nops) },
 	{ MLX5E_DECLARE_RQ_XDPSQ_STAT(struct mlx5e_xdpsq_stats, full) },
 	{ MLX5E_DECLARE_RQ_XDPSQ_STAT(struct mlx5e_xdpsq_stats, err) },
 	{ MLX5E_DECLARE_RQ_XDPSQ_STAT(struct mlx5e_xdpsq_stats, cqes) },
@@ -1340,6 +1345,7 @@ static const struct counter_desc xdpsq_stats_desc[] = {
 	{ MLX5E_DECLARE_XDPSQ_STAT(struct mlx5e_xdpsq_stats, xmit) },
 	{ MLX5E_DECLARE_XDPSQ_STAT(struct mlx5e_xdpsq_stats, mpwqe) },
 	{ MLX5E_DECLARE_XDPSQ_STAT(struct mlx5e_xdpsq_stats, inlnw) },
+	{ MLX5E_DECLARE_XDPSQ_STAT(struct mlx5e_xdpsq_stats, nops) },
 	{ MLX5E_DECLARE_XDPSQ_STAT(struct mlx5e_xdpsq_stats, full) },
 	{ MLX5E_DECLARE_XDPSQ_STAT(struct mlx5e_xdpsq_stats, err) },
 	{ MLX5E_DECLARE_XDPSQ_STAT(struct mlx5e_xdpsq_stats, cqes) },
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
index 76ac111e14d0..bf645d42c833 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
@@ -81,6 +81,7 @@ struct mlx5e_sw_stats {
 	u64 rx_xdp_tx_xmit;
 	u64 rx_xdp_tx_mpwqe;
 	u64 rx_xdp_tx_inlnw;
+	u64 rx_xdp_tx_nops;
 	u64 rx_xdp_tx_full;
 	u64 rx_xdp_tx_err;
 	u64 rx_xdp_tx_cqe;
@@ -97,6 +98,7 @@ struct mlx5e_sw_stats {
 	u64 tx_xdp_xmit;
 	u64 tx_xdp_mpwqe;
 	u64 tx_xdp_inlnw;
+	u64 tx_xdp_nops;
 	u64 tx_xdp_full;
 	u64 tx_xdp_err;
 	u64 tx_xdp_cqes;
@@ -288,6 +290,7 @@ struct mlx5e_xdpsq_stats {
 	u64 xmit;
 	u64 mpwqe;
 	u64 inlnw;
+	u64 nops;
 	u64 full;
 	u64 err;
 	/* dirtied @completion */
-- 
2.21.0


^ permalink raw reply related

* [net-next 01/12] net/mlx5: E-Switch, add ingress rate support
From: Saeed Mahameed @ 2019-08-01 19:56 UTC (permalink / raw)
  To: David S. Miller
  Cc: netdev@vger.kernel.org, Eli Cohen, Paul Blakey, Saeed Mahameed
In-Reply-To: <20190801195620.26180-1-saeedm@mellanox.com>

From: Eli Cohen <eli@mellanox.com>

Use the scheduling elements to implement ingress rate limiter on an
eswitch ports ingress traffic. Since the ingress of eswitch port is the
egress of VF port, we control eswitch ingress by controlling VF egress.

Configuration is done using the ports' representor net devices.

Please note that burst size configuration is not supported by devices
ConnectX-5 and earlier generations.

Configuration examples:
tc:
tc filter add dev enp59s0f0_0 root protocol ip matchall action police rate 1mbit burst 20k

ovs:
ovs-vsctl set interface eth0 ingress_policing_rate=1000

Signed-off-by: Eli Cohen <eli@mellanox.com>
Reviewed-by: Paul Blakey <paulb@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
 .../net/ethernet/mellanox/mlx5/core/en_rep.c  |  19 ++++
 .../net/ethernet/mellanox/mlx5/core/en_rep.h  |   1 +
 .../net/ethernet/mellanox/mlx5/core/en_tc.c   | 100 ++++++++++++++++++
 .../net/ethernet/mellanox/mlx5/core/en_tc.h   |   7 ++
 .../net/ethernet/mellanox/mlx5/core/eswitch.c |  16 +++
 .../net/ethernet/mellanox/mlx5/core/eswitch.h |   2 +
 6 files changed, 145 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 6edf0aeb1e26..bf6f4835457e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -1156,6 +1156,23 @@ mlx5e_rep_setup_tc_cls_flower(struct mlx5e_priv *priv,
 	}
 }
 
+static
+int mlx5e_rep_setup_tc_cls_matchall(struct mlx5e_priv *priv,
+				    struct tc_cls_matchall_offload *ma)
+{
+	switch (ma->command) {
+	case TC_CLSMATCHALL_REPLACE:
+		return mlx5e_tc_configure_matchall(priv, ma);
+	case TC_CLSMATCHALL_DESTROY:
+		return mlx5e_tc_delete_matchall(priv, ma);
+	case TC_CLSMATCHALL_STATS:
+		mlx5e_tc_stats_matchall(priv, ma);
+		return 0;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data,
 				 void *cb_priv)
 {
@@ -1165,6 +1182,8 @@ static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data,
 	switch (type) {
 	case TC_SETUP_CLSFLOWER:
 		return mlx5e_rep_setup_tc_cls_flower(priv, type_data, flags);
+	case TC_SETUP_CLSMATCHALL:
+		return mlx5e_rep_setup_tc_cls_matchall(priv, type_data);
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
index 10fafd5fa17b..43eeebe9c8d2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
@@ -88,6 +88,7 @@ struct mlx5e_rep_priv {
 	struct mlx5_flow_handle *vport_rx_rule;
 	struct list_head       vport_sqs_list;
 	struct mlx5_rep_uplink_priv uplink_priv; /* valid for uplink rep */
+	struct rtnl_link_stats64 prev_vf_vport_stats;
 	struct devlink_port dl_port;
 };
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index f3ed028d5017..dc5fc3350b65 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -3638,6 +3638,106 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
 	return err;
 }
 
+static int apply_police_params(struct mlx5e_priv *priv, u32 rate,
+			       struct netlink_ext_ack *extack)
+{
+	struct mlx5e_rep_priv *rpriv = priv->ppriv;
+	struct mlx5_eswitch *esw;
+	u16 vport_num;
+	u32 rate_mbps;
+	int err;
+
+	esw = priv->mdev->priv.eswitch;
+	/* rate is given in bytes/sec.
+	 * First convert to bits/sec and then round to the nearest mbit/secs.
+	 * mbit means million bits.
+	 * Moreover, if rate is non zero we choose to configure to a minimum of
+	 * 1 mbit/sec.
+	 */
+	rate_mbps = rate ? max_t(u32, (rate * 8 + 500000) / 1000000, 1) : 0;
+	vport_num = rpriv->rep->vport;
+
+	err = mlx5_esw_modify_vport_rate(esw, vport_num, rate_mbps);
+	if (err)
+		NL_SET_ERR_MSG_MOD(extack, "failed applying action to hardware");
+
+	return err;
+}
+
+static int scan_tc_matchall_fdb_actions(struct mlx5e_priv *priv,
+					struct flow_action *flow_action,
+					struct netlink_ext_ack *extack)
+{
+	struct mlx5e_rep_priv *rpriv = priv->ppriv;
+	const struct flow_action_entry *act;
+	int err;
+	int i;
+
+	if (!flow_action_has_entries(flow_action)) {
+		NL_SET_ERR_MSG_MOD(extack, "matchall called with no action");
+		return -EINVAL;
+	}
+
+	if (!flow_offload_has_one_action(flow_action)) {
+		NL_SET_ERR_MSG_MOD(extack, "matchall policing support only a single action");
+		return -EOPNOTSUPP;
+	}
+
+	flow_action_for_each(i, act, flow_action) {
+		switch (act->id) {
+		case FLOW_ACTION_POLICE:
+			err = apply_police_params(priv, act->police.rate_bytes_ps, extack);
+			if (err)
+				return err;
+
+			rpriv->prev_vf_vport_stats = priv->stats.vf_vport;
+			break;
+		default:
+			NL_SET_ERR_MSG_MOD(extack, "mlx5 supports only police action for matchall");
+			return -EOPNOTSUPP;
+		}
+	}
+
+	return 0;
+}
+
+int mlx5e_tc_configure_matchall(struct mlx5e_priv *priv,
+				struct tc_cls_matchall_offload *ma)
+{
+	struct netlink_ext_ack *extack = ma->common.extack;
+	int prio = TC_H_MAJ(ma->common.prio) >> 16;
+
+	if (prio != 1) {
+		NL_SET_ERR_MSG_MOD(extack, "only priority 1 is supported");
+		return -EINVAL;
+	}
+
+	return scan_tc_matchall_fdb_actions(priv, &ma->rule->action, extack);
+}
+
+int mlx5e_tc_delete_matchall(struct mlx5e_priv *priv,
+			     struct tc_cls_matchall_offload *ma)
+{
+	struct netlink_ext_ack *extack = ma->common.extack;
+
+	return apply_police_params(priv, 0, extack);
+}
+
+void mlx5e_tc_stats_matchall(struct mlx5e_priv *priv,
+			     struct tc_cls_matchall_offload *ma)
+{
+	struct mlx5e_rep_priv *rpriv = priv->ppriv;
+	struct rtnl_link_stats64 cur_stats;
+	u64 dbytes;
+	u64 dpkts;
+
+	cur_stats = priv->stats.vf_vport;
+	dpkts = cur_stats.rx_packets - rpriv->prev_vf_vport_stats.rx_packets;
+	dbytes = cur_stats.rx_bytes - rpriv->prev_vf_vport_stats.rx_bytes;
+	rpriv->prev_vf_vport_stats = cur_stats;
+	flow_stats_update(&ma->stats, dpkts, dbytes, jiffies);
+}
+
 static void mlx5e_tc_hairpin_update_dead_peer(struct mlx5e_priv *priv,
 					      struct mlx5e_priv *peer_priv)
 {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
index 1cb66bf76997..20f045e96c92 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
@@ -63,6 +63,13 @@ int mlx5e_delete_flower(struct net_device *dev, struct mlx5e_priv *priv,
 int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
 		       struct flow_cls_offload *f, unsigned long flags);
 
+int mlx5e_tc_configure_matchall(struct mlx5e_priv *priv,
+				struct tc_cls_matchall_offload *f);
+int mlx5e_tc_delete_matchall(struct mlx5e_priv *priv,
+			     struct tc_cls_matchall_offload *f);
+void mlx5e_tc_stats_matchall(struct mlx5e_priv *priv,
+			     struct tc_cls_matchall_offload *ma);
+
 struct mlx5e_encap_entry;
 void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv,
 			      struct mlx5e_encap_entry *e);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
index f4ace5f8e884..5fbebee7254d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
@@ -1585,6 +1585,22 @@ static int esw_vport_qos_config(struct mlx5_eswitch *esw,
 	return 0;
 }
 
+int mlx5_esw_modify_vport_rate(struct mlx5_eswitch *esw, u16 vport_num,
+			       u32 rate_mbps)
+{
+	u32 ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
+	struct mlx5_vport *vport;
+
+	vport = mlx5_eswitch_get_vport(esw, vport_num);
+	MLX5_SET(scheduling_context, ctx, max_average_bw, rate_mbps);
+
+	return mlx5_modify_scheduling_element_cmd(esw->dev,
+						  SCHEDULING_HIERARCHY_E_SWITCH,
+						  ctx,
+						  vport->qos.esw_tsar_ix,
+						  MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW);
+}
+
 static void node_guid_gen_from_mac(u64 *node_guid, u8 mac[ETH_ALEN])
 {
 	((u8 *)node_guid)[7] = mac[0];
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
index 4a03fdadb47e..804912e38dee 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
@@ -261,6 +261,8 @@ void esw_vport_disable_ingress_acl(struct mlx5_eswitch *esw,
 				   struct mlx5_vport *vport);
 void esw_vport_del_ingress_acl_modify_metadata(struct mlx5_eswitch *esw,
 					       struct mlx5_vport *vport);
+int mlx5_esw_modify_vport_rate(struct mlx5_eswitch *esw, u16 vport_num,
+			       u32 rate_mbps);
 
 /* E-Switch API */
 int mlx5_eswitch_init(struct mlx5_core_dev *dev);
-- 
2.21.0


^ permalink raw reply related

* [net-next 04/12] net/mlx5e: Tx, Strict the room needed for SQ edge NOPs
From: Saeed Mahameed @ 2019-08-01 19:56 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev@vger.kernel.org, Tariq Toukan, Saeed Mahameed
In-Reply-To: <20190801195620.26180-1-saeedm@mellanox.com>

From: Tariq Toukan <tariqt@mellanox.com>

We use NOPs to populate the WQ fragment edge if the WQE does not fit
in frag, to avoid WQEs crossing a page boundary (or wrap-around the WQ).

The upper bound on the needed number of NOPs is one WQEBB less than
the largest possible WQE, for otherwise the WQE would certainly fit.

Signed-off-by: Tariq Toukan <tariqt@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h
index ddfe19adb3d9..7da22b413a48 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h
@@ -6,7 +6,7 @@
 
 #include "en.h"
 
-#define MLX5E_SQ_NOPS_ROOM  MLX5_SEND_WQE_MAX_WQEBBS
+#define MLX5E_SQ_NOPS_ROOM (MLX5_SEND_WQE_MAX_WQEBBS - 1)
 #define MLX5E_SQ_STOP_ROOM (MLX5_SEND_WQE_MAX_WQEBBS +\
 			    MLX5E_SQ_NOPS_ROOM)
 
-- 
2.21.0


^ permalink raw reply related

* [net-next 03/12] net/mlx5: Add flow counter pool
From: Saeed Mahameed @ 2019-08-01 19:56 UTC (permalink / raw)
  To: David S. Miller
  Cc: netdev@vger.kernel.org, Gavi Teitz, Vlad Buslov, Saeed Mahameed
In-Reply-To: <20190801195620.26180-1-saeedm@mellanox.com>

From: Gavi Teitz <gavi@mellanox.com>

Add a pool of flow counters, based on flow counter bulks, removing the
need to allocate a new counter via a costly FW command during the flow
creation process. The time it takes to acquire/release a flow counter
is cut from ~50 [us] to ~50 [ns].

The pool is part of the mlx5 driver instance, and provides flow
counters for aging flows. mlx5_fc_create() was modified to provide
counters for aging flows from the pool by default, and
mlx5_destroy_fc() was modified to release counters back to the pool
for later reuse. If bulk allocation is not supported or fails, and for
non-aging flows, the fallback behavior is to allocate and free
individual counters.

The pool is comprised of three lists of flow counter bulks, one of
fully used bulks, one of partially used bulks, and one of unused
bulks. Counters are provided from the partially used bulks first, to
help limit bulk fragmentation.

The pool maintains a threshold, and strives to maintain the amount of
available counters below it. The pool is increased in size when a
counter acquisition request is made and there are no available
counters, and it is decreased in size when the last counter in a bulk
is released and there are more available counters than the threshold.
All pool size changes are done in the context of the
acquiring/releasing process.

The value of the threshold is directly correlated to the amount of
used counters the pool is providing, while constrained by a hard
maximum, and is recalculated every time a bulk is allocated/freed.
This ensures that the pool only consumes large amounts of memory for
available counters if the pool is being used heavily. When fully
populated and at the hard maximum, the buffer of available counters
consumes ~40 [MB].

Signed-off-by: Gavi Teitz <gavi@mellanox.com>
Reviewed-by: Vlad Buslov <vladbu@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
 .../ethernet/mellanox/mlx5/core/fs_counters.c | 231 ++++++++++++++++--
 include/linux/mlx5/driver.h                   |  12 +
 2 files changed, 218 insertions(+), 25 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
index 3e734e62a6cd..51f1736c455d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
@@ -40,6 +40,8 @@
 #define MLX5_FC_STATS_PERIOD msecs_to_jiffies(1000)
 /* Max number of counters to query in bulk read is 32K */
 #define MLX5_SW_MAX_COUNTERS_BULK BIT(15)
+#define MLX5_FC_POOL_MAX_THRESHOLD BIT(18)
+#define MLX5_FC_POOL_USED_BUFF_RATIO 10
 
 struct mlx5_fc_cache {
 	u64 packets;
@@ -65,6 +67,11 @@ struct mlx5_fc {
 	struct mlx5_fc_cache cache ____cacheline_aligned_in_smp;
 };
 
+static void mlx5_fc_pool_init(struct mlx5_fc_pool *fc_pool, struct mlx5_core_dev *dev);
+static void mlx5_fc_pool_cleanup(struct mlx5_fc_pool *fc_pool);
+static struct mlx5_fc *mlx5_fc_pool_acquire_counter(struct mlx5_fc_pool *fc_pool);
+static void mlx5_fc_pool_release_counter(struct mlx5_fc_pool *fc_pool, struct mlx5_fc *fc);
+
 /* locking scheme:
  *
  * It is the responsibility of the user to prevent concurrent calls or bad
@@ -202,13 +209,22 @@ static void mlx5_fc_stats_query_counter_range(struct mlx5_core_dev *dev,
 	}
 }
 
-static void mlx5_free_fc(struct mlx5_core_dev *dev,
-			 struct mlx5_fc *counter)
+static void mlx5_fc_free(struct mlx5_core_dev *dev, struct mlx5_fc *counter)
 {
 	mlx5_cmd_fc_free(dev, counter->id);
 	kfree(counter);
 }
 
+static void mlx5_fc_release(struct mlx5_core_dev *dev, struct mlx5_fc *counter)
+{
+	struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
+
+	if (counter->bulk)
+		mlx5_fc_pool_release_counter(&fc_stats->fc_pool, counter);
+	else
+		mlx5_fc_free(dev, counter);
+}
+
 static void mlx5_fc_stats_work(struct work_struct *work)
 {
 	struct mlx5_core_dev *dev = container_of(work, struct mlx5_core_dev,
@@ -232,7 +248,7 @@ static void mlx5_fc_stats_work(struct work_struct *work)
 	llist_for_each_entry_safe(counter, tmp, dellist, dellist) {
 		mlx5_fc_stats_remove(dev, counter);
 
-		mlx5_free_fc(dev, counter);
+		mlx5_fc_release(dev, counter);
 	}
 
 	if (time_before(now, fc_stats->next_query) ||
@@ -248,26 +264,56 @@ static void mlx5_fc_stats_work(struct work_struct *work)
 	fc_stats->next_query = now + fc_stats->sampling_interval;
 }
 
-struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging)
+static struct mlx5_fc *mlx5_fc_single_alloc(struct mlx5_core_dev *dev)
 {
-	struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
 	struct mlx5_fc *counter;
 	int err;
 
 	counter = kzalloc(sizeof(*counter), GFP_KERNEL);
 	if (!counter)
 		return ERR_PTR(-ENOMEM);
-	INIT_LIST_HEAD(&counter->list);
 
 	err = mlx5_cmd_fc_alloc(dev, &counter->id);
-	if (err)
-		goto err_out;
+	if (err) {
+		kfree(counter);
+		return ERR_PTR(err);
+	}
+
+	return counter;
+}
+
+static struct mlx5_fc *mlx5_fc_acquire(struct mlx5_core_dev *dev, bool aging)
+{
+	struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
+	struct mlx5_fc *counter;
+
+	if (aging && MLX5_CAP_GEN(dev, flow_counter_bulk_alloc) != 0) {
+		counter = mlx5_fc_pool_acquire_counter(&fc_stats->fc_pool);
+		if (!IS_ERR(counter))
+			return counter;
+	}
+
+	return mlx5_fc_single_alloc(dev);
+}
+
+struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging)
+{
+	struct mlx5_fc *counter = mlx5_fc_acquire(dev, aging);
+	struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
+	int err;
+
+	if (IS_ERR(counter))
+		return counter;
+
+	INIT_LIST_HEAD(&counter->list);
+	counter->aging = aging;
 
 	if (aging) {
 		u32 id = counter->id;
 
 		counter->cache.lastuse = jiffies;
-		counter->aging = true;
+		counter->lastbytes = counter->cache.bytes;
+		counter->lastpackets = counter->cache.packets;
 
 		idr_preload(GFP_KERNEL);
 		spin_lock(&fc_stats->counters_idr_lock);
@@ -288,10 +334,7 @@ struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging)
 	return counter;
 
 err_out_alloc:
-	mlx5_cmd_fc_free(dev, counter->id);
-err_out:
-	kfree(counter);
-
+	mlx5_fc_release(dev, counter);
 	return ERR_PTR(err);
 }
 EXPORT_SYMBOL(mlx5_fc_create);
@@ -315,7 +358,7 @@ void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter)
 		return;
 	}
 
-	mlx5_free_fc(dev, counter);
+	mlx5_fc_release(dev, counter);
 }
 EXPORT_SYMBOL(mlx5_fc_destroy);
 
@@ -344,6 +387,7 @@ int mlx5_init_fc_stats(struct mlx5_core_dev *dev)
 	fc_stats->sampling_interval = MLX5_FC_STATS_PERIOD;
 	INIT_DELAYED_WORK(&fc_stats->work, mlx5_fc_stats_work);
 
+	mlx5_fc_pool_init(&fc_stats->fc_pool, dev);
 	return 0;
 
 err_wq_create:
@@ -358,6 +402,7 @@ void mlx5_cleanup_fc_stats(struct mlx5_core_dev *dev)
 	struct mlx5_fc *counter;
 	struct mlx5_fc *tmp;
 
+	mlx5_fc_pool_cleanup(&fc_stats->fc_pool);
 	cancel_delayed_work_sync(&dev->priv.fc_stats.work);
 	destroy_workqueue(dev->priv.fc_stats.wq);
 	dev->priv.fc_stats.wq = NULL;
@@ -368,10 +413,10 @@ void mlx5_cleanup_fc_stats(struct mlx5_core_dev *dev)
 
 	tmplist = llist_del_all(&fc_stats->addlist);
 	llist_for_each_entry_safe(counter, tmp, tmplist, addlist)
-		mlx5_free_fc(dev, counter);
+		mlx5_fc_release(dev, counter);
 
 	list_for_each_entry_safe(counter, tmp, &fc_stats->counters, list)
-		mlx5_free_fc(dev, counter);
+		mlx5_fc_release(dev, counter);
 }
 
 int mlx5_fc_query(struct mlx5_core_dev *dev, struct mlx5_fc *counter,
@@ -417,14 +462,15 @@ void mlx5_fc_update_sampling_interval(struct mlx5_core_dev *dev,
 /* Flow counter bluks */
 
 struct mlx5_fc_bulk {
+	struct list_head pool_list;
 	u32 base_id;
 	int bulk_len;
 	unsigned long *bitmask;
 	struct mlx5_fc fcs[0];
 };
 
-static void
-mlx5_fc_init(struct mlx5_fc *counter, struct mlx5_fc_bulk *bulk, u32 id)
+static void mlx5_fc_init(struct mlx5_fc *counter, struct mlx5_fc_bulk *bulk,
+			 u32 id)
 {
 	counter->bulk = bulk;
 	counter->id = id;
@@ -435,8 +481,7 @@ static int mlx5_fc_bulk_get_free_fcs_amount(struct mlx5_fc_bulk *bulk)
 	return bitmap_weight(bulk->bitmask, bulk->bulk_len);
 }
 
-static struct mlx5_fc_bulk __attribute__((unused))
-*mlx5_fc_bulk_create(struct mlx5_core_dev *dev)
+static struct mlx5_fc_bulk *mlx5_fc_bulk_create(struct mlx5_core_dev *dev)
 {
 	enum mlx5_fc_bulk_alloc_bitmask alloc_bitmask;
 	struct mlx5_fc_bulk *bulk;
@@ -479,7 +524,7 @@ static struct mlx5_fc_bulk __attribute__((unused))
 	return ERR_PTR(err);
 }
 
-static int __attribute__((unused))
+static int
 mlx5_fc_bulk_destroy(struct mlx5_core_dev *dev, struct mlx5_fc_bulk *bulk)
 {
 	if (mlx5_fc_bulk_get_free_fcs_amount(bulk) < bulk->bulk_len) {
@@ -494,8 +539,7 @@ mlx5_fc_bulk_destroy(struct mlx5_core_dev *dev, struct mlx5_fc_bulk *bulk)
 	return 0;
 }
 
-static struct mlx5_fc __attribute__((unused))
-*mlx5_fc_bulk_acquire_fc(struct mlx5_fc_bulk *bulk)
+static struct mlx5_fc *mlx5_fc_bulk_acquire_fc(struct mlx5_fc_bulk *bulk)
 {
 	int free_fc_index = find_first_bit(bulk->bitmask, bulk->bulk_len);
 
@@ -506,8 +550,7 @@ static struct mlx5_fc __attribute__((unused))
 	return &bulk->fcs[free_fc_index];
 }
 
-static int __attribute__((unused))
-mlx5_fc_bulk_release_fc(struct mlx5_fc_bulk *bulk, struct mlx5_fc *fc)
+static int mlx5_fc_bulk_release_fc(struct mlx5_fc_bulk *bulk, struct mlx5_fc *fc)
 {
 	int fc_index = fc->id - bulk->base_id;
 
@@ -517,3 +560,141 @@ mlx5_fc_bulk_release_fc(struct mlx5_fc_bulk *bulk, struct mlx5_fc *fc)
 	set_bit(fc_index, bulk->bitmask);
 	return 0;
 }
+
+/* Flow counters pool API */
+
+static void mlx5_fc_pool_init(struct mlx5_fc_pool *fc_pool, struct mlx5_core_dev *dev)
+{
+	fc_pool->dev = dev;
+	mutex_init(&fc_pool->pool_lock);
+	INIT_LIST_HEAD(&fc_pool->fully_used);
+	INIT_LIST_HEAD(&fc_pool->partially_used);
+	INIT_LIST_HEAD(&fc_pool->unused);
+	fc_pool->available_fcs = 0;
+	fc_pool->used_fcs = 0;
+	fc_pool->threshold = 0;
+}
+
+static void mlx5_fc_pool_cleanup(struct mlx5_fc_pool *fc_pool)
+{
+	struct mlx5_core_dev *dev = fc_pool->dev;
+	struct mlx5_fc_bulk *bulk;
+	struct mlx5_fc_bulk *tmp;
+
+	list_for_each_entry_safe(bulk, tmp, &fc_pool->fully_used, pool_list)
+		mlx5_fc_bulk_destroy(dev, bulk);
+	list_for_each_entry_safe(bulk, tmp, &fc_pool->partially_used, pool_list)
+		mlx5_fc_bulk_destroy(dev, bulk);
+	list_for_each_entry_safe(bulk, tmp, &fc_pool->unused, pool_list)
+		mlx5_fc_bulk_destroy(dev, bulk);
+}
+
+static void mlx5_fc_pool_update_threshold(struct mlx5_fc_pool *fc_pool)
+{
+	fc_pool->threshold = min_t(int, MLX5_FC_POOL_MAX_THRESHOLD,
+				   fc_pool->used_fcs / MLX5_FC_POOL_USED_BUFF_RATIO);
+}
+
+static struct mlx5_fc_bulk *
+mlx5_fc_pool_alloc_new_bulk(struct mlx5_fc_pool *fc_pool)
+{
+	struct mlx5_core_dev *dev = fc_pool->dev;
+	struct mlx5_fc_bulk *new_bulk;
+
+	new_bulk = mlx5_fc_bulk_create(dev);
+	if (!IS_ERR(new_bulk))
+		fc_pool->available_fcs += new_bulk->bulk_len;
+	mlx5_fc_pool_update_threshold(fc_pool);
+	return new_bulk;
+}
+
+static void
+mlx5_fc_pool_free_bulk(struct mlx5_fc_pool *fc_pool, struct mlx5_fc_bulk *bulk)
+{
+	struct mlx5_core_dev *dev = fc_pool->dev;
+
+	fc_pool->available_fcs -= bulk->bulk_len;
+	mlx5_fc_bulk_destroy(dev, bulk);
+	mlx5_fc_pool_update_threshold(fc_pool);
+}
+
+static struct mlx5_fc *
+mlx5_fc_pool_acquire_from_list(struct list_head *src_list,
+			       struct list_head *next_list,
+			       bool move_non_full_bulk)
+{
+	struct mlx5_fc_bulk *bulk;
+	struct mlx5_fc *fc;
+
+	if (list_empty(src_list))
+		return ERR_PTR(-ENODATA);
+
+	bulk = list_first_entry(src_list, struct mlx5_fc_bulk, pool_list);
+	fc = mlx5_fc_bulk_acquire_fc(bulk);
+	if (move_non_full_bulk || mlx5_fc_bulk_get_free_fcs_amount(bulk) == 0)
+		list_move(&bulk->pool_list, next_list);
+	return fc;
+}
+
+static struct mlx5_fc *
+mlx5_fc_pool_acquire_counter(struct mlx5_fc_pool *fc_pool)
+{
+	struct mlx5_fc_bulk *new_bulk;
+	struct mlx5_fc *fc;
+
+	mutex_lock(&fc_pool->pool_lock);
+
+	fc = mlx5_fc_pool_acquire_from_list(&fc_pool->partially_used,
+					    &fc_pool->fully_used, false);
+	if (IS_ERR(fc))
+		fc = mlx5_fc_pool_acquire_from_list(&fc_pool->unused,
+						    &fc_pool->partially_used,
+						    true);
+	if (IS_ERR(fc)) {
+		new_bulk = mlx5_fc_pool_alloc_new_bulk(fc_pool);
+		if (IS_ERR(new_bulk)) {
+			fc = ERR_CAST(new_bulk);
+			goto out;
+		}
+		fc = mlx5_fc_bulk_acquire_fc(new_bulk);
+		list_add(&new_bulk->pool_list, &fc_pool->partially_used);
+	}
+	fc_pool->available_fcs--;
+	fc_pool->used_fcs++;
+
+out:
+	mutex_unlock(&fc_pool->pool_lock);
+	return fc;
+}
+
+static void
+mlx5_fc_pool_release_counter(struct mlx5_fc_pool *fc_pool, struct mlx5_fc *fc)
+{
+	struct mlx5_core_dev *dev = fc_pool->dev;
+	struct mlx5_fc_bulk *bulk = fc->bulk;
+	int bulk_free_fcs_amount;
+
+	mutex_lock(&fc_pool->pool_lock);
+
+	if (mlx5_fc_bulk_release_fc(bulk, fc)) {
+		mlx5_core_warn(dev, "Attempted to release a counter which is not acquired\n");
+		goto unlock;
+	}
+
+	fc_pool->available_fcs++;
+	fc_pool->used_fcs--;
+
+	bulk_free_fcs_amount = mlx5_fc_bulk_get_free_fcs_amount(bulk);
+	if (bulk_free_fcs_amount == 1)
+		list_move_tail(&bulk->pool_list, &fc_pool->partially_used);
+	if (bulk_free_fcs_amount == bulk->bulk_len) {
+		list_del(&bulk->pool_list);
+		if (fc_pool->available_fcs > fc_pool->threshold)
+			mlx5_fc_pool_free_bulk(fc_pool, bulk);
+		else
+			list_add(&bulk->pool_list, &fc_pool->unused);
+	}
+
+unlock:
+	mutex_unlock(&fc_pool->pool_lock);
+}
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index 267b2bc0ca4a..d8f348ef9c33 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -477,6 +477,17 @@ struct mlx5_core_sriov {
 	u16			max_vfs;
 };
 
+struct mlx5_fc_pool {
+	struct mlx5_core_dev *dev;
+	struct mutex pool_lock; /* protects pool lists */
+	struct list_head fully_used;
+	struct list_head partially_used;
+	struct list_head unused;
+	int available_fcs;
+	int used_fcs;
+	int threshold;
+};
+
 struct mlx5_fc_stats {
 	spinlock_t counters_idr_lock; /* protects counters_idr */
 	struct idr counters_idr;
@@ -489,6 +500,7 @@ struct mlx5_fc_stats {
 	unsigned long next_query;
 	unsigned long sampling_interval; /* jiffies */
 	u32 *bulk_query_out;
+	struct mlx5_fc_pool fc_pool;
 };
 
 struct mlx5_events;
-- 
2.21.0


^ permalink raw reply related

* [net-next 02/12] net/mlx5: Add flow counter bulk infrastructure
From: Saeed Mahameed @ 2019-08-01 19:56 UTC (permalink / raw)
  To: David S. Miller
  Cc: netdev@vger.kernel.org, Gavi Teitz, Vlad Buslov, Saeed Mahameed
In-Reply-To: <20190801195620.26180-1-saeedm@mellanox.com>

From: Gavi Teitz <gavi@mellanox.com>

Add infrastructure to track bulks of flow counters, providing
the means to allocate and deallocate bulks, and to acquire and
release individual counters from the bulks.

Signed-off-by: Gavi Teitz <gavi@mellanox.com>
Reviewed-by: Vlad Buslov <vladbu@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
 .../ethernet/mellanox/mlx5/core/fs_counters.c | 105 ++++++++++++++++++
 1 file changed, 105 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
index 067a4b56498b..3e734e62a6cd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
@@ -58,6 +58,7 @@ struct mlx5_fc {
 	u64 lastpackets;
 	u64 lastbytes;
 
+	struct mlx5_fc_bulk *bulk;
 	u32 id;
 	bool aging;
 
@@ -412,3 +413,107 @@ void mlx5_fc_update_sampling_interval(struct mlx5_core_dev *dev,
 	fc_stats->sampling_interval = min_t(unsigned long, interval,
 					    fc_stats->sampling_interval);
 }
+
+/* Flow counter bluks */
+
+struct mlx5_fc_bulk {
+	u32 base_id;
+	int bulk_len;
+	unsigned long *bitmask;
+	struct mlx5_fc fcs[0];
+};
+
+static void
+mlx5_fc_init(struct mlx5_fc *counter, struct mlx5_fc_bulk *bulk, u32 id)
+{
+	counter->bulk = bulk;
+	counter->id = id;
+}
+
+static int mlx5_fc_bulk_get_free_fcs_amount(struct mlx5_fc_bulk *bulk)
+{
+	return bitmap_weight(bulk->bitmask, bulk->bulk_len);
+}
+
+static struct mlx5_fc_bulk __attribute__((unused))
+*mlx5_fc_bulk_create(struct mlx5_core_dev *dev)
+{
+	enum mlx5_fc_bulk_alloc_bitmask alloc_bitmask;
+	struct mlx5_fc_bulk *bulk;
+	int err = -ENOMEM;
+	int bulk_len;
+	u32 base_id;
+	int i;
+
+	alloc_bitmask = MLX5_CAP_GEN(dev, flow_counter_bulk_alloc);
+	bulk_len = alloc_bitmask > 0 ? MLX5_FC_BULK_NUM_FCS(alloc_bitmask) : 1;
+
+	bulk = kzalloc(sizeof(*bulk) + bulk_len * sizeof(struct mlx5_fc),
+		       GFP_KERNEL);
+	if (!bulk)
+		goto err_alloc_bulk;
+
+	bulk->bitmask = kcalloc(BITS_TO_LONGS(bulk_len), sizeof(unsigned long),
+				GFP_KERNEL);
+	if (!bulk->bitmask)
+		goto err_alloc_bitmask;
+
+	err = mlx5_cmd_fc_bulk_alloc(dev, alloc_bitmask, &base_id);
+	if (err)
+		goto err_mlx5_cmd_bulk_alloc;
+
+	bulk->base_id = base_id;
+	bulk->bulk_len = bulk_len;
+	for (i = 0; i < bulk_len; i++) {
+		mlx5_fc_init(&bulk->fcs[i], bulk, base_id + i);
+		set_bit(i, bulk->bitmask);
+	}
+
+	return bulk;
+
+err_mlx5_cmd_bulk_alloc:
+	kfree(bulk->bitmask);
+err_alloc_bitmask:
+	kfree(bulk);
+err_alloc_bulk:
+	return ERR_PTR(err);
+}
+
+static int __attribute__((unused))
+mlx5_fc_bulk_destroy(struct mlx5_core_dev *dev, struct mlx5_fc_bulk *bulk)
+{
+	if (mlx5_fc_bulk_get_free_fcs_amount(bulk) < bulk->bulk_len) {
+		mlx5_core_err(dev, "Freeing bulk before all counters were released\n");
+		return -EBUSY;
+	}
+
+	mlx5_cmd_fc_free(dev, bulk->base_id);
+	kfree(bulk->bitmask);
+	kfree(bulk);
+
+	return 0;
+}
+
+static struct mlx5_fc __attribute__((unused))
+*mlx5_fc_bulk_acquire_fc(struct mlx5_fc_bulk *bulk)
+{
+	int free_fc_index = find_first_bit(bulk->bitmask, bulk->bulk_len);
+
+	if (free_fc_index >= bulk->bulk_len)
+		return ERR_PTR(-ENOSPC);
+
+	clear_bit(free_fc_index, bulk->bitmask);
+	return &bulk->fcs[free_fc_index];
+}
+
+static int __attribute__((unused))
+mlx5_fc_bulk_release_fc(struct mlx5_fc_bulk *bulk, struct mlx5_fc *fc)
+{
+	int fc_index = fc->id - bulk->base_id;
+
+	if (test_bit(fc_index, bulk->bitmask))
+		return -EINVAL;
+
+	set_bit(fc_index, bulk->bitmask);
+	return 0;
+}
-- 
2.21.0


^ permalink raw reply related

* [pull request][net-next 00/12] Mellanox, mlx5 updates 2019-08-01
From: Saeed Mahameed @ 2019-08-01 19:56 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev@vger.kernel.org, Saeed Mahameed

Hi Dave,

This series provides misc updates to mlx5 driver.
For more information please see tag log below.

Please pull and let me know if there is any problem.

Please note that the series starts with a merge of mlx5-next branch,
to resolve and avoid dependency with rdma tree.

Thanks,
Saeed.

---
The following changes since commit 68e18626dfe971df3856872ee58f63c389dea2f5:

  Merge branch 'mlx5-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mellanox/linux (2019-08-01 12:33:14 -0700)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux.git tags/mlx5-updates-2019-08-01

for you to fetch changes up to 6830b468259b45e3b73070474b8cec9388aa8c11:

  net/mlx5e: Allow dropping specific tunnel packets (2019-08-01 12:33:33 -0700)

----------------------------------------------------------------
mlx5-updates-2019-08-01

Misc updates for mlx5 netdev driver:

1) Ingress rate support for E-Switch vports from Eli.
2) Gavi introduces flow counters bulk allocation and pool,
   To improve the performance of flow counter acquisition.
3) From Tariq, micro improvements for tx path
4) From Shay, small improvement for XDP TX MPWQE inline flow.
5) Aya provides some cleanups for tx devlink health reporters.
6) Saeed, refactor checksum handling into a single function.
7) Tonghao, allows dropping specific tunnel packets.

----------------------------------------------------------------
Aya Levin (3):
      net/mlx5e: Fix mlx5e_tx_reporter_create return value
      net/mlx5e: Set tx reporter only on successful creation
      net/mlx5e: TX reporter cleanup

Eli Cohen (1):
      net/mlx5: E-Switch, add ingress rate support

Gavi Teitz (2):
      net/mlx5: Add flow counter bulk infrastructure
      net/mlx5: Add flow counter pool

Saeed Mahameed (1):
      net/mlx5e: Rx, checksum handling refactoring

Shay Agroskin (1):
      net/mlx5e: XDP, Close TX MPWQE session when no room for inline packet left

Tariq Toukan (3):
      net/mlx5e: Tx, Strict the room needed for SQ edge NOPs
      net/mlx5e: XDP, Slight enhancement for WQE fetch function
      net/mlx5e: Tx, Soften inline mode VLAN dependencies

Tonghao Zhang (1):
      net/mlx5e: Allow dropping specific tunnel packets

 drivers/net/ethernet/mellanox/mlx5/core/en.h       |   4 +-
 .../net/ethernet/mellanox/mlx5/core/en/reporter.h  |   1 -
 .../ethernet/mellanox/mlx5/core/en/reporter_tx.c   |  17 +-
 drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h  |  24 +-
 drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c   |  36 +--
 drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h   |  66 ++++-
 .../net/ethernet/mellanox/mlx5/core/en_common.c    |  12 -
 drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c |   2 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_main.c  |   6 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_rep.c   |  19 ++
 drivers/net/ethernet/mellanox/mlx5/core/en_rep.h   |   1 +
 drivers/net/ethernet/mellanox/mlx5/core/en_rx.c    |  26 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_stats.c |   6 +
 drivers/net/ethernet/mellanox/mlx5/core/en_stats.h |   3 +
 drivers/net/ethernet/mellanox/mlx5/core/en_tc.c    | 103 ++++++-
 drivers/net/ethernet/mellanox/mlx5/core/en_tc.h    |   7 +
 drivers/net/ethernet/mellanox/mlx5/core/en_tx.c    |   7 +-
 drivers/net/ethernet/mellanox/mlx5/core/eswitch.c  |  16 ++
 drivers/net/ethernet/mellanox/mlx5/core/eswitch.h  |   2 +
 .../net/ethernet/mellanox/mlx5/core/fs_counters.c  | 318 +++++++++++++++++++--
 drivers/net/ethernet/mellanox/mlx5/core/vport.c    |   7 +-
 include/linux/mlx5/driver.h                        |  12 +
 22 files changed, 592 insertions(+), 103 deletions(-)

^ permalink raw reply

* Re: [PATCH v3 0/3] auth_gss: netns refcount leaks when use-gss-proxy==1
From: J. Bruce Fields @ 2019-08-01 19:53 UTC (permalink / raw)
  To: Wenbin Zeng
  Cc: davem, viro, jlayton, trond.myklebust, anna.schumaker, wenbinzeng,
	dsahern, nicolas.dichtel, willy, edumazet, jakub.kicinski,
	tyhicks, chuck.lever, neilb, linux-fsdevel, linux-kernel, netdev,
	linux-nfs
In-Reply-To: <1560341370-24197-1-git-send-email-wenbinzeng@tencent.com>

I lost track, what happened to these patches?

--b.

On Wed, Jun 12, 2019 at 08:09:27PM +0800, Wenbin Zeng wrote:
> This patch series fixes an auth_gss bug that results in netns refcount
> leaks when use-gss-proxy is set to 1.
> 
> The problem was found in privileged docker containers with gssproxy service
> enabled and /proc/net/rpc/use-gss-proxy set to 1, the corresponding
> struct net->count ends up at 2 after container gets killed, the consequence
> is that the struct net cannot be freed.
> 
> It turns out that write_gssp() called gssp_rpc_create() to create a rpc
> client, this increases net->count by 2; rpcsec_gss_exit_net() is supposed
> to decrease net->count but it never gets called because its call-path is:
>         net->count==0 -> cleanup_net -> ops_exit_list -> rpcsec_gss_exit_net
> Before rpcsec_gss_exit_net() gets called, net->count cannot reach 0, this
> is a deadlock situation.
> 
> To fix the problem, we must break the deadlock, rpcsec_gss_exit_net()
> should move out of the put() path and find another chance to get called,
> I think nsfs_evict() is a good place to go, when netns inode gets evicted
> we call rpcsec_gss_exit_net() to free the rpc client, this requires a new
> callback i.e. evict to be added in struct proc_ns_operations, and add
> netns_evict() as one of netns_operations as well.
> 
> v1->v2:
>  * in nsfs_evict(), move ->evict() in front of ->put()
> v2->v3:
>  * rpcsec_gss_evict_net() directly call gss_svc_shutdown_net() regardless
>    if gssp_clnt is null, this is exactly same to what rpcsec_gss_exit_net()
>    previously did
> 
> Wenbin Zeng (3):
>   nsfs: add evict callback into struct proc_ns_operations
>   netns: add netns_evict into netns_operations
>   auth_gss: fix deadlock that blocks rpcsec_gss_exit_net when
>     use-gss-proxy==1
> 
>  fs/nsfs.c                      |  2 ++
>  include/linux/proc_ns.h        |  1 +
>  include/net/net_namespace.h    |  1 +
>  net/core/net_namespace.c       | 12 ++++++++++++
>  net/sunrpc/auth_gss/auth_gss.c |  4 ++--
>  5 files changed, 18 insertions(+), 2 deletions(-)
> 
> -- 
> 1.8.3.1

^ permalink raw reply

* Re: [PATCH net] ipv4/route: do not check saddr dev if iif is LOOPBACK_IFINDEX
From: David Ahern @ 2019-08-01 19:51 UTC (permalink / raw)
  To: Hangbin Liu, netdev
  Cc: Stefano Brivio, Marcelo Ricardo Leitner, David Ahern,
	David S . Miller
In-Reply-To: <20190801082900.27216-1-liuhangbin@gmail.com>

On 8/1/19 2:29 AM, Hangbin Liu wrote:
> Jianlin reported a bug that for IPv4, ip route get from src_addr would fail
> if src_addr is not an address on local system.
> 
> \# ip route get 1.1.1.1 from 2.2.2.2
> RTNETLINK answers: Invalid argument

so this is a forwarding lookup in which case iif should be set. Based on
the above 'route get' inet_rtm_getroute is doing a lookup as if it is
locally generated traffic.

^ permalink raw reply

* Re: [PATCH] net: bridge: Allow bridge to joing multicast groups
From: Horatiu Vultur @ 2019-08-01 19:48 UTC (permalink / raw)
  To: Vivien Didelot
  Cc: roopa, nikolay, davem, bridge, netdev, linux-kernel,
	allan.nielsen
In-Reply-To: <20190801151739.GB32290@t480s.localdomain>

Hi Vivien,

The 08/01/2019 15:17, Vivien Didelot wrote:
> External E-Mail
> 
> I'm a bit late in the conversation. Isn't this what you want?
> 
>     ip address add <multicast IPv4 address> dev br0 autojoin
> 

Not really, I was looking in a way to register the ports to link layer
multicast address. Sorry for the confusion, my description of the patch
was totally missleaning.

If you follow this thread you will get a better idea what we wanted to
achive. We got some really good comments and based on these we send a
RFC[1]. 

> 
> Thanks,
> Vivien

[1] https://patchwork.ozlabs.org/patch/1140468/

-- 
/Horatiu

^ permalink raw reply

* Re: [PATCH] net: bridge: Allow bridge to joing multicast groups
From: Vivien Didelot @ 2019-08-01 19:17 UTC (permalink / raw)
  To: Horatiu Vultur
  Cc: roopa, nikolay, davem, bridge, netdev, linux-kernel,
	allan.nielsen, Horatiu Vultur
In-Reply-To: <1564055044-27593-1-git-send-email-horatiu.vultur@microchip.com>

Hi Horatiu,

On Thu, 25 Jul 2019 13:44:04 +0200, Horatiu Vultur <horatiu.vultur@microchip.com> wrote:
> There is no way to configure the bridge, to receive only specific link
> layer multicast addresses. From the description of the command 'bridge
> fdb append' is supposed to do that, but there was no way to notify the
> network driver that the bridge joined a group, because LLADDR was added
> to the unicast netdev_hw_addr_list.
> 
> Therefore update fdb_add_entry to check if the NLM_F_APPEND flag is set
> and if the source is NULL, which represent the bridge itself. Then add
> address to multicast netdev_hw_addr_list for each bridge interfaces.
> And then the .ndo_set_rx_mode function on the driver is called. To notify
> the driver that the list of multicast mac addresses changed.
> 
> Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
> ---
>  net/bridge/br_fdb.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 46 insertions(+), 3 deletions(-)
> 
> diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
> index b1d3248..d93746d 100644
> --- a/net/bridge/br_fdb.c
> +++ b/net/bridge/br_fdb.c
> @@ -175,6 +175,29 @@ static void fdb_add_hw_addr(struct net_bridge *br, const unsigned char *addr)
>  	}
>  }
>  
> +static void fdb_add_hw_maddr(struct net_bridge *br, const unsigned char *addr)
> +{
> +	int err;
> +	struct net_bridge_port *p;
> +
> +	ASSERT_RTNL();
> +
> +	list_for_each_entry(p, &br->port_list, list) {
> +		if (!br_promisc_port(p)) {
> +			err = dev_mc_add(p->dev, addr);
> +			if (err)
> +				goto undo;
> +		}
> +	}
> +
> +	return;
> +undo:
> +	list_for_each_entry_continue_reverse(p, &br->port_list, list) {
> +		if (!br_promisc_port(p))
> +			dev_mc_del(p->dev, addr);
> +	}
> +}
> +
>  /* When a static FDB entry is deleted, the HW address from that entry is
>   * also removed from the bridge private HW address list and updates all
>   * the ports with needed information.
> @@ -192,13 +215,27 @@ static void fdb_del_hw_addr(struct net_bridge *br, const unsigned char *addr)
>  	}
>  }
>  
> +static void fdb_del_hw_maddr(struct net_bridge *br, const unsigned char *addr)
> +{
> +	struct net_bridge_port *p;
> +
> +	ASSERT_RTNL();
> +
> +	list_for_each_entry(p, &br->port_list, list) {
> +		if (!br_promisc_port(p))
> +			dev_mc_del(p->dev, addr);
> +	}
> +}
> +
>  static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f,
>  		       bool swdev_notify)
>  {
>  	trace_fdb_delete(br, f);
>  
> -	if (f->is_static)
> +	if (f->is_static) {
>  		fdb_del_hw_addr(br, f->key.addr.addr);
> +		fdb_del_hw_maddr(br, f->key.addr.addr);
> +	}
>  
>  	hlist_del_init_rcu(&f->fdb_node);
>  	rhashtable_remove_fast(&br->fdb_hash_tbl, &f->rhnode,
> @@ -843,13 +880,19 @@ static int fdb_add_entry(struct net_bridge *br, struct net_bridge_port *source,
>  			fdb->is_local = 1;
>  			if (!fdb->is_static) {
>  				fdb->is_static = 1;
> -				fdb_add_hw_addr(br, addr);
> +				if (flags & NLM_F_APPEND && !source)
> +					fdb_add_hw_maddr(br, addr);
> +				else
> +					fdb_add_hw_addr(br, addr);
>  			}
>  		} else if (state & NUD_NOARP) {
>  			fdb->is_local = 0;
>  			if (!fdb->is_static) {
>  				fdb->is_static = 1;
> -				fdb_add_hw_addr(br, addr);
> +				if (flags & NLM_F_APPEND && !source)
> +					fdb_add_hw_maddr(br, addr);
> +				else
> +					fdb_add_hw_addr(br, addr);
>  			}
>  		} else {
>  			fdb->is_local = 0;
> -- 
> 2.7.4
> 

I'm a bit late in the conversation. Isn't this what you want?

    ip address add <multicast IPv4 address> dev br0 autojoin


Thanks,
Vivien

^ permalink raw reply

* Re: [PATCH net-next] net/mlx5e: Allow dropping specific tunnel packets
From: Saeed Mahameed @ 2019-08-01 19:14 UTC (permalink / raw)
  To: Roi Dayan, xiangxia.m.yue@gmail.com; +Cc: netdev@vger.kernel.org
In-Reply-To: <1564648859-17369-1-git-send-email-xiangxia.m.yue@gmail.com>

On Thu, 2019-08-01 at 16:40 +0800, xiangxia.m.yue@gmail.com wrote:
> From: Tonghao Zhang <xiangxia.m.yue@gmail.com>
> 
> In some case, we don't want to allow specific tunnel packets
> to host that can avoid to take up high CPU (e.g network attacks).
> But other tunnel packets which not matched in hardware will be
> sent to host too.
> 
>     $ tc filter add dev vxlan_sys_4789 \
> 	    protocol ip chain 0 parent ffff: prio 1 handle 1 \
> 	    flower dst_ip 1.1.1.100 ip_proto tcp dst_port 80 \
> 	    enc_dst_ip 2.2.2.100 enc_key_id 100 enc_dst_port 4789 \
> 	    action tunnel_key unset pipe action drop
> 
> Signed-off-by: Tonghao Zhang <xiangxia.m.yue@gmail.com>

Applied to net-next-mlx5.

Thanks!

^ permalink raw reply

* [PATCH v4 0/4] net: phy: realtek: Enable configuration of RTL8211E LEDs
From: Matthias Kaehlcke @ 2019-08-01 19:07 UTC (permalink / raw)
  To: David S . Miller, Rob Herring, Mark Rutland, Andrew Lunn,
	Florian Fainelli, Heiner Kallweit
  Cc: netdev, devicetree, linux-kernel, Douglas Anderson,
	Matthias Kaehlcke

The Realtek RTL8211E allows customization of the PHY LED behavior,
like which LEDs are on for certain link speeds and which LEDs blink
when there is traffic. By default EEE LED mode is enabled, in which
a blinking LED is on for 400ms and off for 2s. This series adds a
generic device tree binding for configuring PHY LEDs and adds LED
configuration support for the RTL8211E PHY.

Certain registers of the RTL8211E can only be accessed through
a vendor specific extended page mechanism. Extended pages need
to be accessed for the LED configuration. This series adds helpers
to facilitate accessing extended pages.

Matthias Kaehlcke (4):
  dt-bindings: net: phy: Add subnode for LED configuration
  net: phy: Add function to retrieve LED configuration from the DT
  net: phy: realtek: Add helpers for accessing RTL8211E extension pages
  net: phy: realtek: configure RTL8211E LEDs

 .../devicetree/bindings/net/ethernet-phy.yaml |  47 +++++
 drivers/net/phy/phy_device.c                  |  50 ++++++
 drivers/net/phy/realtek.c                     | 169 ++++++++++++++++--
 include/linux/phy.h                           |  15 ++
 4 files changed, 266 insertions(+), 15 deletions(-)

-- 
2.22.0.770.g0f2c4a37fd-goog


^ permalink raw reply

* [PATCH v4 2/4] net: phy: Add function to retrieve LED configuration from the DT
From: Matthias Kaehlcke @ 2019-08-01 19:07 UTC (permalink / raw)
  To: David S . Miller, Rob Herring, Mark Rutland, Andrew Lunn,
	Florian Fainelli, Heiner Kallweit
  Cc: netdev, devicetree, linux-kernel, Douglas Anderson,
	Matthias Kaehlcke
In-Reply-To: <20190801190759.28201-1-mka@chromium.org>

Add a phylib function for retrieving PHY LED configuration that
is specified in the device tree using the generic binding. LEDs
can be configured to be 'on' for a certain link speed or to blink
when there is TX/RX activity.

Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
---
Changes in v4:
- patch added to the series
---
 drivers/net/phy/phy_device.c | 50 ++++++++++++++++++++++++++++++++++++
 include/linux/phy.h          | 15 +++++++++++
 2 files changed, 65 insertions(+)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 6b5cb87f3866..b4b48de45712 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -2188,6 +2188,56 @@ static bool phy_drv_supports_irq(struct phy_driver *phydrv)
 	return phydrv->config_intr && phydrv->ack_interrupt;
 }
 
+int of_get_phy_led_cfg(struct phy_device *phydev, int led,
+		       struct phy_led_config *cfg)
+{
+	struct device_node *np, *child;
+	const char *trigger;
+	int ret;
+
+	if (!IS_ENABLED(CONFIG_OF_MDIO))
+		return -ENOENT;
+
+	np = of_find_node_by_name(phydev->mdio.dev.of_node, "leds");
+	if (!np)
+		return -ENOENT;
+
+	for_each_child_of_node(np, child) {
+		u32 val;
+
+		if (!of_property_read_u32(child, "reg", &val)) {
+			if (val == (u32)led)
+				break;
+		}
+	}
+
+	if (!child)
+		return -ENOENT;
+
+	ret = of_property_read_string(child, "linux,default-trigger",
+				      &trigger);
+	if (ret)
+		return ret;
+
+	if (!strcmp(trigger, "phy_link_10m_active")) {
+		cfg->trigger = PHY_LED_LINK_10M;
+	} else if (!strcmp(trigger, "phy_link_100m_active")) {
+		cfg->trigger = PHY_LED_LINK_100M;
+	} else if (!strcmp(trigger, "phy_link_1g_active")) {
+		cfg->trigger = PHY_LED_LINK_1G;
+	} else if (!strcmp(trigger, "phy_link_10g_active")) {
+		cfg->trigger = PHY_LED_LINK_10G;
+	}  else if (!strcmp(trigger, "phy_activity")) {
+		cfg->trigger = PHY_LED_ACTIVITY;
+	} else {
+		phydev_warn(phydev, "trigger '%s' for LED%d is invalid\n",
+			    trigger, led);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 /**
  * phy_probe - probe and init a PHY device
  * @dev: device to probe and init
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 462b90b73f93..b4693415be31 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1176,6 +1176,21 @@ int phy_ethtool_set_link_ksettings(struct net_device *ndev,
 				   const struct ethtool_link_ksettings *cmd);
 int phy_ethtool_nway_reset(struct net_device *ndev);
 
+enum phy_led_trigger {
+	PHY_LED_LINK_10M,
+	PHY_LED_LINK_100M,
+	PHY_LED_LINK_1G,
+	PHY_LED_LINK_10G,
+	PHY_LED_ACTIVITY,
+};
+
+struct phy_led_config {
+	enum phy_led_trigger trigger;
+};
+
+int of_get_phy_led_cfg(struct phy_device *phydev, int led,
+		       struct phy_led_config *cfg);
+
 #if IS_ENABLED(CONFIG_PHYLIB)
 int __init mdio_bus_init(void);
 void mdio_bus_exit(void);
-- 
2.22.0.770.g0f2c4a37fd-goog


^ permalink raw reply related

* [PATCH v4 1/4] dt-bindings: net: phy: Add subnode for LED configuration
From: Matthias Kaehlcke @ 2019-08-01 19:07 UTC (permalink / raw)
  To: David S . Miller, Rob Herring, Mark Rutland, Andrew Lunn,
	Florian Fainelli, Heiner Kallweit
  Cc: netdev, devicetree, linux-kernel, Douglas Anderson,
	Matthias Kaehlcke
In-Reply-To: <20190801190759.28201-1-mka@chromium.org>

The LED behavior of some Ethernet PHYs is configurable. Add an
optional 'leds' subnode with a child node for each LED to be
configured. The binding aims to be compatible with the common
LED binding (see devicetree/bindings/leds/common.txt).

A LED can be configured to be 'on' when a link with a certain speed
is active, or to blink on RX/TX activity. For the configuration to
be effective it needs to be supported by the hardware and the
corresponding PHY driver.

Suggested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
---
Changes in v4:
- patch added to the series
---
 .../devicetree/bindings/net/ethernet-phy.yaml | 47 +++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/ethernet-phy.yaml b/Documentation/devicetree/bindings/net/ethernet-phy.yaml
index f70f18ff821f..81c5aacc89a5 100644
--- a/Documentation/devicetree/bindings/net/ethernet-phy.yaml
+++ b/Documentation/devicetree/bindings/net/ethernet-phy.yaml
@@ -153,6 +153,38 @@ properties:
       Delay after the reset was deasserted in microseconds. If
       this property is missing the delay will be skipped.
 
+patternProperties:
+  "^leds$":
+    type: object
+    description:
+      Subnode with configuration of the PHY LEDs.
+
+    patternProperties:
+      "^led@[0-9]+$":
+        type: object
+        description:
+          Subnode with the configuration of a single PHY LED.
+
+    properties:
+      reg:
+        description:
+          The ID number of the LED, typically corresponds to a hardware ID.
+        $ref: "/schemas/types.yaml#/definitions/uint32"
+
+      linux,default-trigger:
+        description:
+          This parameter, if present, is a string specifying the trigger
+          assigned to the LED. Supported triggers are:
+            "phy_link_10m_active" - LED will be on when a 10Mb/s link is active
+            "phy_link_100m_active" - LED will be on when a 100Mb/s link is active
+            "phy_link_1g_active" - LED will be on when a 1Gb/s link is active
+            "phy_link_10g_active" - LED will be on when a 10Gb/s link is active
+            "phy_activity" - LED will blink when data is received or transmitted
+        $ref: "/schemas/types.yaml#/definitions/string"
+
+    required:
+      - reg
+
 required:
   - reg
 
@@ -173,5 +205,20 @@ examples:
             reset-gpios = <&gpio1 4 1>;
             reset-assert-us = <1000>;
             reset-deassert-us = <2000>;
+
+            leds {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                led@0 {
+                    reg = <0>;
+                    linux,default-trigger = "phy_link_1g_active";
+                };
+
+                led@1 {
+                    reg = <1>;
+                    linux,default-trigger = "phy_activity";
+                };
+            };
         };
     };
-- 
2.22.0.770.g0f2c4a37fd-goog


^ permalink raw reply related

* [PATCH v4 4/4] net: phy: realtek: configure RTL8211E LEDs
From: Matthias Kaehlcke @ 2019-08-01 19:07 UTC (permalink / raw)
  To: David S . Miller, Rob Herring, Mark Rutland, Andrew Lunn,
	Florian Fainelli, Heiner Kallweit
  Cc: netdev, devicetree, linux-kernel, Douglas Anderson,
	Matthias Kaehlcke
In-Reply-To: <20190801190759.28201-1-mka@chromium.org>

Configure the RTL8211E LEDs behavior when the device tree property
'realtek,led-modes' is specified.

Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
---
Changes in v4:
- use the generic PHY LED binding
- keep default/current configuration if none is specified
- added rtl8211e_disable_eee_led_mode()
  - was previously in separate patch, however since we always want to
    disable EEE LED mode when a LED configuration is specified it makes
    sense to just add the function here.
- don't call phy_restore_page() in rtl8211e_config_leds() if
  selection of the extended page failed.
- use phydev_warn() instead of phydev_err() if LED configuration
  fails since we don't bail out
- use hex number to specify page for consistency
- add hex number to comment about ext page 44 to facilitate searching
---
 drivers/net/phy/realtek.c | 121 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 120 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index e09d3b0da2c7..46e3d77d41b6 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -9,8 +9,11 @@
  * Copyright (c) 2004 Freescale Semiconductor, Inc.
  */
 #include <linux/bitops.h>
-#include <linux/phy.h>
+#include <linux/bits.h>
 #include <linux/module.h>
+#include <linux/phy.h>
+
+#define RTL821x_NUM_LEDS			3
 
 #define RTL821x_PHYSR				0x11
 #define RTL821x_PHYSR_DUPLEX			BIT(13)
@@ -26,6 +29,19 @@
 #define RTL821x_EXT_PAGE_SELECT			0x1e
 #define RTL821x_PAGE_SELECT			0x1f
 
+/* RTL8211E page 5 */
+#define RTL8211E_EEE_LED_MODE1			0x05
+#define RTL8211E_EEE_LED_MODE2			0x06
+
+/* RTL8211E extension page 44 (0x2c) */
+#define RTL8211E_LACR				0x1a
+#define RLT8211E_LACR_LEDACTCTRL_SHIFT		4
+#define RLT8211E_LACR_LEDACTCTRL_MASK		GENMASK(6, 4)
+#define RTL8211E_LCR				0x1c
+#define RTL8211E_LCR_LEDCTRL_MASK		(GENMASK(2, 0) | \
+						 GENMASK(6, 4) | \
+						 GENMASK(10, 8))
+
 #define RTL8211F_INSR				0x1d
 
 #define RTL8211F_TX_DELAY			BIT(8)
@@ -83,6 +99,105 @@ static int rtl8211e_modify_ext_paged(struct phy_device *phydev, int page,
 	return phy_restore_page(phydev, oldpage, ret);
 }
 
+static void rtl8211e_disable_eee_led_mode(struct phy_device *phydev)
+{
+	int oldpage;
+	int err = 0;
+
+	oldpage = phy_select_page(phydev, 5);
+	if (oldpage < 0)
+		goto out;
+
+	/* write magic values to disable EEE LED mode */
+	err = __phy_write(phydev, RTL8211E_EEE_LED_MODE1, 0x8b82);
+	if (err)
+		goto out;
+
+	err = __phy_write(phydev, RTL8211E_EEE_LED_MODE2, 0x052b);
+
+out:
+	phy_restore_page(phydev, oldpage, err);
+}
+
+static int rtl8211e_config_leds(struct phy_device *phydev)
+{
+	int i, oldpage, ret;
+	u16 lacr_bits = 0, lcr_bits = 0;
+	u16 lacr_mask = RLT8211E_LACR_LEDACTCTRL_MASK;
+	u16 lcr_mask = RTL8211E_LCR_LEDCTRL_MASK;
+	bool eed_led_mode_disabled = false;
+
+	for (i = 0; i < RTL821x_NUM_LEDS; i++) {
+		struct phy_led_config cfg;
+
+		ret = of_get_phy_led_cfg(phydev, i, &cfg);
+		if (ret) {
+			lacr_mask &= ~BIT(4 + i);
+			lcr_mask &= ~GENMASK((i * 4) + 2, i * 4);
+			continue;
+		}
+
+		if (!eed_led_mode_disabled) {
+			rtl8211e_disable_eee_led_mode(phydev);
+			eed_led_mode_disabled = true;
+		}
+
+		switch (cfg.trigger) {
+		case PHY_LED_LINK_10M:
+			lcr_bits |= 1 << (i * 4);
+			break;
+
+		case PHY_LED_LINK_100M:
+			lcr_bits |= 2 << (i * 4);
+			break;
+
+		case PHY_LED_LINK_1G:
+			lcr_bits |= 4 << (i * 4);
+			break;
+
+		case PHY_LED_ACTIVITY:
+			lacr_bits |= BIT(RLT8211E_LACR_LEDACTCTRL_SHIFT + i);
+			break;
+
+		default:
+			phydev_warn(phydev,
+				    "unknown trigger for LED%d: %d\n",
+				    i, cfg.trigger);
+		}
+	}
+
+	oldpage = rtl8211e_select_ext_page(phydev, 0x2c);
+	if (oldpage < 0) {
+		phydev_err(phydev, "failed to select extended page: %d\n", oldpage);
+		return oldpage;
+	}
+
+	if (lacr_mask == 0)
+		goto skip_lacr;
+
+	ret = __phy_modify(phydev, RTL8211E_LACR,
+			   lacr_mask, lacr_bits);
+	if (ret) {
+		phydev_err(phydev, "failed to write LACR reg: %d\n",
+			   ret);
+		goto err;
+	}
+
+skip_lacr:
+	if (lcr_mask == 0)
+		goto skip_lcr;
+
+	ret = __phy_modify(phydev, RTL8211E_LCR,
+			   lcr_mask, lcr_bits);
+	if (ret)
+		phydev_err(phydev, "failed to write LCR reg: %d\n",
+			   ret);
+
+skip_lcr:
+err:
+	return phy_restore_page(phydev, oldpage, ret);
+}
+
 static int rtl8201_ack_interrupt(struct phy_device *phydev)
 {
 	int err;
@@ -217,6 +332,10 @@ static int rtl8211e_config_init(struct phy_device *phydev)
 	int ret;
 	u16 val;
 
+	ret = rtl8211e_config_leds(phydev);
+	if (ret)
+		phydev_warn(phydev, "LED configuration failed: %d\n", ret);
+
 	/* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */
 	switch (phydev->interface) {
 	case PHY_INTERFACE_MODE_RGMII:
-- 
2.22.0.770.g0f2c4a37fd-goog


^ permalink raw reply related

* [PATCH v4 3/4] net: phy: realtek: Add helpers for accessing RTL8211E extension pages
From: Matthias Kaehlcke @ 2019-08-01 19:07 UTC (permalink / raw)
  To: David S . Miller, Rob Herring, Mark Rutland, Andrew Lunn,
	Florian Fainelli, Heiner Kallweit
  Cc: netdev, devicetree, linux-kernel, Douglas Anderson,
	Matthias Kaehlcke
In-Reply-To: <20190801190759.28201-1-mka@chromium.org>

The RTL8211E has extension pages, which can be accessed after
selecting a page through a custom method. Add a function to
modify bits in a register of an extension page and a helper for
selecting an ext page. Use rtl8211e_modify_ext_paged() in
rtl8211e_config_init() instead of doing things 'manually'.

Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
---
Changes in v4:
- don't add constant RTL8211E_EXT_PAGE, it's only used once,
  use a literal instead
- pass 'oldpage' to phy_restore_page() in rtl8211e_select_ext_page(),
  not 'page'
- return 'oldpage' in rtl8211e_select_ext_page()
- use __phy_modify() in rtl8211e_modify_ext_paged() instead of
  reimplementing __phy_modify_changed()
- in rtl8211e_modify_ext_paged() return directly when
  rtl8211e_select_ext_page() fails
---
 drivers/net/phy/realtek.c | 48 +++++++++++++++++++++++++++------------
 1 file changed, 34 insertions(+), 14 deletions(-)

diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index a669945eb829..e09d3b0da2c7 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -53,6 +53,36 @@ static int rtl821x_write_page(struct phy_device *phydev, int page)
 	return __phy_write(phydev, RTL821x_PAGE_SELECT, page);
 }
 
+static int rtl8211e_select_ext_page(struct phy_device *phydev, int page)
+{
+	int ret, oldpage;
+
+	oldpage = phy_select_page(phydev, 7);
+	if (oldpage < 0)
+		return oldpage;
+
+	ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, page);
+	if (ret)
+		return phy_restore_page(phydev, oldpage, ret);
+
+	return oldpage;
+}
+
+static int rtl8211e_modify_ext_paged(struct phy_device *phydev, int page,
+				     u32 regnum, u16 mask, u16 set)
+{
+	int ret = 0;
+	int oldpage;
+
+	oldpage = rtl8211e_select_ext_page(phydev, page);
+	if (oldpage < 0)
+		return oldpage;
+
+	ret = __phy_modify(phydev, regnum, mask, set);
+
+	return phy_restore_page(phydev, oldpage, ret);
+}
+
 static int rtl8201_ack_interrupt(struct phy_device *phydev)
 {
 	int err;
@@ -184,7 +214,7 @@ static int rtl8211f_config_init(struct phy_device *phydev)
 
 static int rtl8211e_config_init(struct phy_device *phydev)
 {
-	int ret = 0, oldpage;
+	int ret;
 	u16 val;
 
 	/* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */
@@ -213,19 +243,9 @@ static int rtl8211e_config_init(struct phy_device *phydev)
 	 * 2 = RX Delay, 1 = TX Delay, 0 = SELRGV (see original PHY datasheet
 	 * for details).
 	 */
-	oldpage = phy_select_page(phydev, 0x7);
-	if (oldpage < 0)
-		goto err_restore_page;
-
-	ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, 0xa4);
-	if (ret)
-		goto err_restore_page;
-
-	ret = __phy_modify(phydev, 0x1c, RTL8211E_TX_DELAY | RTL8211E_RX_DELAY,
-			   val);
-
-err_restore_page:
-	return phy_restore_page(phydev, oldpage, ret);
+	return rtl8211e_modify_ext_paged(phydev, 0xa4, 0x1c,
+					 RTL8211E_TX_DELAY | RTL8211E_RX_DELAY,
+					 val);
 }
 
 static int rtl8211b_suspend(struct phy_device *phydev)
-- 
2.22.0.770.g0f2c4a37fd-goog


^ permalink raw reply related

* [PATCH net-next 06/15] selftests: Add ipv6 tcp tests to fcnal-test
From: David Ahern @ 2019-08-01 18:56 UTC (permalink / raw)
  To: davem; +Cc: netdev, David Ahern
In-Reply-To: <20190801185648.27653-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Add IPv6 tcp tests to fcnal-test.sh. Covers the permutations of directly
connected addresses, routed destinations, VRF and non-VRF, and expected
failures for both clients and servers. Includes permutations with
net.ipv4.tcp_l3mdev_accept set to 0 and 1.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 tools/testing/selftests/net/fcnal-test.sh | 370 +++++++++++++++++++++++++++++-
 1 file changed, 369 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh
index f9e2f1464dcd..97291c6d17c5 100755
--- a/tools/testing/selftests/net/fcnal-test.sh
+++ b/tools/testing/selftests/net/fcnal-test.sh
@@ -1304,6 +1304,373 @@ ipv6_ping()
 }
 
 ################################################################################
+# IPv6 TCP
+
+ipv6_tcp_novrf()
+{
+	local a
+
+	#
+	# server tests
+	#
+	for a in ${NSA_IP6} ${NSA_LO_IP6} ${NSA_LINKIP6}%${NSB_DEV}
+	do
+		log_start
+		run_cmd nettest -6 -s &
+		sleep 1
+		run_cmd_nsb nettest -6 -r ${a}
+		log_test_addr ${a} $? 0 "Global server"
+	done
+
+	# verify TCP reset received
+	for a in ${NSA_IP6} ${NSA_LO_IP6} ${NSA_LINKIP6}%${NSB_DEV}
+	do
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd_nsb nettest -6 -r ${a}
+		log_test_addr ${a} $? 1 "No server"
+	done
+
+	#
+	# client
+	#
+	for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6}%${NSA_DEV}
+	do
+		log_start
+		run_cmd_nsb nettest -6 -s &
+		sleep 1
+		run_cmd nettest -6 -r ${a}
+		log_test_addr ${a} $? 0 "Client"
+	done
+
+	for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6}%${NSA_DEV}
+	do
+		log_start
+		run_cmd_nsb nettest -6 -s &
+		sleep 1
+		run_cmd nettest -6 -r ${a} -d ${NSA_DEV}
+		log_test_addr ${a} $? 0 "Client, device bind"
+	done
+
+	for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6}%${NSA_DEV}
+	do
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd nettest -6 -r ${a} -d ${NSA_DEV}
+		log_test_addr ${a} $? 1 "No server, device client"
+	done
+
+	#
+	# local address tests
+	#
+	for a in ${NSA_IP6} ${NSA_LO_IP6} ::1
+	do
+		log_start
+		run_cmd nettest -6 -s &
+		sleep 1
+		run_cmd nettest -6 -r ${a}
+		log_test_addr ${a} $? 0 "Global server, local connection"
+	done
+
+	a=${NSA_IP6}
+	log_start
+	run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -6 -r ${a} -0 ${a}
+	log_test_addr ${a} $? 0 "Device server, unbound client, local connection"
+
+	for a in ${NSA_LO_IP6} ::1
+	do
+		log_start
+		show_hint "Should fail 'Connection refused' since addresses on loopback are out of device scope"
+		run_cmd nettest -6 -s -d ${NSA_DEV} &
+		sleep 1
+		run_cmd nettest -6 -r ${a}
+		log_test_addr ${a} $? 1 "Device server, unbound client, local connection"
+	done
+
+	a=${NSA_IP6}
+	log_start
+	run_cmd nettest -6 -s &
+	sleep 1
+	run_cmd nettest -6 -r ${a} -d ${NSA_DEV} -0 ${a}
+	log_test_addr ${a} $? 0 "Global server, device client, local connection"
+
+	for a in ${NSA_LO_IP6} ::1
+	do
+		log_start
+		show_hint "Should fail 'Connection refused' since addresses on loopback are out of device scope"
+		run_cmd nettest -6 -s &
+		sleep 1
+		run_cmd nettest -6 -r ${a} -d ${NSA_DEV}
+		log_test_addr ${a} $? 1 "Global server, device client, local connection"
+	done
+
+	for a in ${NSA_IP6} ${NSA_LINKIP6}
+	do
+		log_start
+		run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd nettest -6  -d ${NSA_DEV} -r ${a}
+		log_test_addr ${a} $? 0 "Device server, device client, local conn"
+	done
+
+	for a in ${NSA_IP6} ${NSA_LINKIP6}
+	do
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd nettest -6 -d ${NSA_DEV} -r ${a}
+		log_test_addr ${a} $? 1 "No server, device client, local conn"
+	done
+}
+
+ipv6_tcp_vrf()
+{
+	local a
+
+	# disable global server
+	log_subsection "Global server disabled"
+
+	set_sysctl net.ipv4.tcp_l3mdev_accept=0
+
+	#
+	# server tests
+	#
+	for a in ${NSA_IP6} ${VRF_IP6} ${NSA_LINKIP6}%${NSB_DEV}
+	do
+		log_start
+		show_hint "Should fail 'Connection refused' since global server with VRF is disabled"
+		run_cmd nettest -6 -s &
+		sleep 1
+		run_cmd_nsb nettest -6 -r ${a}
+		log_test_addr ${a} $? 1 "Global server"
+	done
+
+	for a in ${NSA_IP6} ${VRF_IP6}
+	do
+		log_start
+		run_cmd nettest -6 -s -d ${VRF} -2 ${VRF} &
+		sleep 1
+		run_cmd_nsb nettest -6 -r ${a}
+		log_test_addr ${a} $? 0 "VRF server"
+	done
+
+	# link local is always bound to ingress device
+	a=${NSA_LINKIP6}%${NSB_DEV}
+	log_start
+	run_cmd nettest -6 -s -d ${VRF} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd_nsb nettest -6 -r ${a}
+	log_test_addr ${a} $? 0 "VRF server"
+
+	for a in ${NSA_IP6} ${VRF_IP6} ${NSA_LINKIP6}%${NSB_DEV}
+	do
+		log_start
+		run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd_nsb nettest -6 -r ${a}
+		log_test_addr ${a} $? 0 "Device server"
+	done
+
+	# verify TCP reset received
+	for a in ${NSA_IP6} ${VRF_IP6} ${NSA_LINKIP6}%${NSB_DEV}
+	do
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd_nsb nettest -6 -r ${a}
+		log_test_addr ${a} $? 1 "No server"
+	done
+
+	# local address tests
+	a=${NSA_IP6}
+	log_start
+	show_hint "Should fail 'Connection refused' since global server with VRF is disabled"
+	run_cmd nettest -6 -s &
+	sleep 1
+	run_cmd nettest -6 -r ${a} -d ${NSA_DEV}
+	log_test_addr ${a} $? 1 "Global server, local connection"
+
+	#
+	# enable VRF global server
+	#
+	log_subsection "VRF Global server enabled"
+	set_sysctl net.ipv4.tcp_l3mdev_accept=1
+
+	for a in ${NSA_IP6} ${VRF_IP6}
+	do
+		log_start
+		run_cmd nettest -6 -s -2 ${VRF} &
+		sleep 1
+		run_cmd_nsb nettest -6 -r ${a}
+		log_test_addr ${a} $? 0 "Global server"
+	done
+
+	for a in ${NSA_IP6} ${VRF_IP6}
+	do
+		log_start
+		run_cmd nettest -6 -s -d ${VRF} -2 ${VRF} &
+		sleep 1
+		run_cmd_nsb nettest -6 -r ${a}
+		log_test_addr ${a} $? 0 "VRF server"
+	done
+
+	# For LLA, child socket is bound to device
+	a=${NSA_LINKIP6}%${NSB_DEV}
+	log_start
+	run_cmd nettest -6 -s -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd_nsb nettest -6 -r ${a}
+	log_test_addr ${a} $? 0 "Global server"
+
+	log_start
+	run_cmd nettest -6 -s -d ${VRF} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd_nsb nettest -6 -r ${a}
+	log_test_addr ${a} $? 0 "VRF server"
+
+	for a in ${NSA_IP6} ${NSA_LINKIP6}%${NSB_DEV}
+	do
+		log_start
+		run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd_nsb nettest -6 -r ${a}
+		log_test_addr ${a} $? 0 "Device server"
+	done
+
+	# verify TCP reset received
+	for a in ${NSA_IP6} ${VRF_IP6} ${NSA_LINKIP6}%${NSB_DEV}
+	do
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd_nsb nettest -6 -r ${a}
+		log_test_addr ${a} $? 1 "No server"
+	done
+
+	# local address tests
+	for a in ${NSA_IP6} ${VRF_IP6}
+	do
+		log_start
+		show_hint "Fails 'No route to host' since client is not in VRF"
+		run_cmd nettest -6 -s -2 ${VRF} &
+		sleep 1
+		run_cmd nettest -6 -r ${a}
+		log_test_addr ${a} $? 1 "Global server, local connection"
+	done
+
+
+	#
+	# client
+	#
+	for a in ${NSB_IP6} ${NSB_LO_IP6}
+	do
+		log_start
+		run_cmd_nsb nettest -6 -s &
+		sleep 1
+		run_cmd nettest -6 -r ${a} -d ${VRF}
+		log_test_addr ${a} $? 0 "Client, VRF bind"
+	done
+
+	a=${NSB_LINKIP6}
+	log_start
+	show_hint "Fails since VRF device does not allow linklocal addresses"
+	run_cmd_nsb nettest -6 -s &
+	sleep 1
+	run_cmd nettest -6 -r ${a} -d ${VRF}
+	log_test_addr ${a} $? 1 "Client, VRF bind"
+
+	for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6}
+	do
+		log_start
+		run_cmd_nsb nettest -6 -s &
+		sleep 1
+		run_cmd nettest -6 -r ${a} -d ${NSA_DEV}
+		log_test_addr ${a} $? 0 "Client, device bind"
+	done
+
+	for a in ${NSB_IP6} ${NSB_LO_IP6}
+	do
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd nettest -6 -r ${a} -d ${VRF}
+		log_test_addr ${a} $? 1 "No server, VRF client"
+	done
+
+	for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6}
+	do
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd nettest -6 -r ${a} -d ${NSA_DEV}
+		log_test_addr ${a} $? 1 "No server, device client"
+	done
+
+	for a in ${NSA_IP6} ${VRF_IP6} ::1
+	do
+		log_start
+		run_cmd nettest -6 -s -d ${VRF} -2 ${VRF} &
+		sleep 1
+		run_cmd nettest -6 -r ${a} -d ${VRF} -0 ${a}
+		log_test_addr ${a} $? 0 "VRF server, VRF client, local connection"
+	done
+
+	a=${NSA_IP6}
+	log_start
+	run_cmd nettest -6 -s -d ${VRF} -2 ${VRF} &
+	sleep 1
+	run_cmd nettest -6 -r ${a} -d ${NSA_DEV} -0 ${a}
+	log_test_addr ${a} $? 0 "VRF server, device client, local connection"
+
+	a=${NSA_IP6}
+	log_start
+	show_hint "Should fail since unbound client is out of VRF scope"
+	run_cmd nettest -6 -s -d ${VRF} &
+	sleep 1
+	run_cmd nettest -6 -r ${a}
+	log_test_addr ${a} $? 1 "VRF server, unbound client, local connection"
+
+	log_start
+	run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -6 -r ${a} -d ${VRF} -0 ${a}
+	log_test_addr ${a} $? 0 "Device server, VRF client, local connection"
+
+	for a in ${NSA_IP6} ${NSA_LINKIP6}
+	do
+		log_start
+		run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd nettest -6 -r ${a} -d ${NSA_DEV} -0 ${a}
+		log_test_addr ${a} $? 0 "Device server, device client, local connection"
+	done
+}
+
+ipv6_tcp()
+{
+	log_section "IPv6/TCP"
+
+	which nettest >/dev/null
+	if [ $? -ne 0 ]; then
+		log_error "nettest not found; skipping tests"
+		return
+	fi
+
+	log_subsection "No VRF"
+	setup
+
+	# tcp_l3mdev_accept should have no affect without VRF;
+	# run tests with it enabled and disabled to verify
+	log_subsection "tcp_l3mdev_accept disabled"
+	set_sysctl net.ipv4.tcp_l3mdev_accept=0
+	ipv6_tcp_novrf
+	log_subsection "tcp_l3mdev_accept enabled"
+	set_sysctl net.ipv4.tcp_l3mdev_accept=1
+	ipv6_tcp_novrf
+
+	log_subsection "With VRF"
+	setup "yes"
+	ipv6_tcp_vrf
+}
+
+################################################################################
 # usage
 
 usage()
@@ -1324,7 +1691,7 @@ EOF
 # main
 
 TESTS_IPV4="ipv4_ping ipv4_tcp"
-TESTS_IPV6="ipv6_ping"
+TESTS_IPV6="ipv6_ping ipv6_tcp"
 PAUSE_ON_FAIL=no
 PAUSE=no
 
@@ -1366,6 +1733,7 @@ do
 	ipv4_tcp|tcp)    ipv4_tcp;;
 
 	ipv6_ping|ping6) ipv6_ping;;
+	ipv6_tcp|tcp6)   ipv6_tcp;;
 
 	# setup namespaces and config, but do not run any tests
 	setup)		 setup; exit 0;;
-- 
2.11.0


^ permalink raw reply related

* [PATCH net-next 08/15] selftests: Add ipv6 udp tests to fcnal-test
From: David Ahern @ 2019-08-01 18:56 UTC (permalink / raw)
  To: davem; +Cc: netdev, David Ahern
In-Reply-To: <20190801185648.27653-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Add IPv6 udp tests to fcnal-test.sh. Covers the permutations of directly
connected addresses, routed destinations, VRF and non-VRF, and expected
failures for both clients and servers. Includes permutations with
net.ipv4.udp_l3mdev_accept set to 0 and 1.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 tools/testing/selftests/net/fcnal-test.sh | 492 +++++++++++++++++++++++++++++-
 1 file changed, 491 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh
index afe9eb55d04a..2a2e692bc242 100755
--- a/tools/testing/selftests/net/fcnal-test.sh
+++ b/tools/testing/selftests/net/fcnal-test.sh
@@ -2049,6 +2049,495 @@ ipv6_tcp()
 }
 
 ################################################################################
+# IPv6 UDP
+
+ipv6_udp_novrf()
+{
+	local a
+
+	#
+	# server tests
+	#
+	for a in ${NSA_IP6} ${NSA_LINKIP6}%${NSB_DEV}
+	do
+		log_start
+		run_cmd nettest -6 -D -s -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd_nsb nettest -6 -D -r ${a}
+		log_test_addr ${a} $? 0 "Global server"
+
+		log_start
+		run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd_nsb nettest -6 -D -r ${a}
+		log_test_addr ${a} $? 0 "Device server"
+	done
+
+	a=${NSA_LO_IP6}
+	log_start
+	run_cmd nettest -6 -D -s -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd_nsb nettest -6 -D -r ${a}
+	log_test_addr ${a} $? 0 "Global server"
+
+	# should fail since loopback address is out of scope for a device
+	# bound server, but it does not - hence this is more documenting
+	# behavior.
+	#log_start
+	#show_hint "Should fail since loopback address is out of scope"
+	#run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} &
+	#sleep 1
+	#run_cmd_nsb nettest -6 -D -r ${a}
+	#log_test_addr ${a} $? 1 "Device server"
+
+	# negative test - should fail
+	for a in ${NSA_IP6} ${NSA_LO_IP6} ${NSA_LINKIP6}%${NSB_DEV}
+	do
+		log_start
+		show_hint "Should fail 'Connection refused' since there is no server"
+		run_cmd_nsb nettest -6 -D -r ${a}
+		log_test_addr ${a} $? 1 "No server"
+	done
+
+	#
+	# client
+	#
+	for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6}%${NSA_DEV}
+	do
+		log_start
+		run_cmd_nsb nettest -6 -D -s &
+		sleep 1
+		run_cmd nettest -6 -D -r ${a} -0 ${NSA_IP6}
+		log_test_addr ${a} $? 0 "Client"
+
+		log_start
+		run_cmd_nsb nettest -6 -D -s &
+		sleep 1
+		run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV} -0 ${NSA_IP6}
+		log_test_addr ${a} $? 0 "Client, device bind"
+
+		log_start
+		run_cmd_nsb nettest -6 -D -s &
+		sleep 1
+		run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV} -C -0 ${NSA_IP6}
+		log_test_addr ${a} $? 0 "Client, device send via cmsg"
+
+		log_start
+		run_cmd_nsb nettest -6 -D -s &
+		sleep 1
+		run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV} -S -0 ${NSA_IP6}
+		log_test_addr ${a} $? 0 "Client, device bind via IPV6_UNICAST_IF"
+
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd nettest -6 -D -r ${a}
+		log_test_addr ${a} $? 1 "No server, unbound client"
+
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV}
+		log_test_addr ${a} $? 1 "No server, device client"
+	done
+
+	#
+	# local address tests
+	#
+	for a in ${NSA_IP6} ${NSA_LO_IP6} ::1
+	do
+		log_start
+		run_cmd nettest -6 -D -s &
+		sleep 1
+		run_cmd nettest -6 -D -r ${a} -0 ${a} -1 ${a}
+		log_test_addr ${a} $? 0 "Global server, local connection"
+	done
+
+	a=${NSA_IP6}
+	log_start
+	run_cmd nettest -6 -s -D -d ${NSA_DEV} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -6 -D -r ${a}
+	log_test_addr ${a} $? 0 "Device server, unbound client, local connection"
+
+	for a in ${NSA_LO_IP6} ::1
+	do
+		log_start
+		show_hint "Should fail 'Connection refused' since address is out of device scope"
+		run_cmd nettest -6 -s -D -d ${NSA_DEV} &
+		sleep 1
+		run_cmd nettest -6 -D -r ${a}
+		log_test_addr ${a} $? 1 "Device server, local connection"
+	done
+
+	a=${NSA_IP6}
+	log_start
+	run_cmd nettest -6 -s -D &
+	sleep 1
+	run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a}
+	log_test_addr ${a} $? 0 "Global server, device client, local connection"
+
+	log_start
+	run_cmd nettest -6 -s -D &
+	sleep 1
+	run_cmd nettest -6 -D -d ${NSA_DEV} -C -r ${a}
+	log_test_addr ${a} $? 0 "Global server, device send via cmsg, local connection"
+
+	log_start
+	run_cmd nettest -6 -s -D &
+	sleep 1
+	run_cmd nettest -6 -D -d ${NSA_DEV} -S -r ${a}
+	log_test_addr ${a} $? 0 "Global server, device client via IPV6_UNICAST_IF, local connection"
+
+	for a in ${NSA_LO_IP6} ::1
+	do
+		log_start
+		show_hint "Should fail 'No route to host' since addresses on loopback are out of device scope"
+		run_cmd nettest -6 -D -s &
+		sleep 1
+		run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV}
+		log_test_addr ${a} $? 1 "Global server, device client, local connection"
+
+		log_start
+		show_hint "Should fail 'No route to host' since addresses on loopback are out of device scope"
+		run_cmd nettest -6 -D -s &
+		sleep 1
+		run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV} -C
+		log_test_addr ${a} $? 1 "Global server, device send via cmsg, local connection"
+
+		log_start
+		show_hint "Should fail 'No route to host' since addresses on loopback are out of device scope"
+		run_cmd nettest -6 -D -s &
+		sleep 1
+		run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV} -S
+		log_test_addr ${a} $? 1 "Global server, device client via IP_UNICAST_IF, local connection"
+	done
+
+	a=${NSA_IP6}
+	log_start
+	run_cmd nettest -6 -D -s -d ${NSA_DEV} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a} -0 ${a}
+	log_test_addr ${a} $? 0 "Device server, device client, local conn"
+
+	log_start
+	show_hint "Should fail 'Connection refused'"
+	run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a}
+	log_test_addr ${a} $? 1 "No server, device client, local conn"
+
+	# LLA to GUA
+	run_cmd_nsb ip -6 addr del ${NSB_IP6}/64 dev ${NSB_DEV}
+	run_cmd_nsb ip -6 ro add ${NSA_IP6}/128 dev ${NSB_DEV}
+	log_start
+	run_cmd nettest -6 -s -D &
+	sleep 1
+	run_cmd_nsb nettest -6 -D -r ${NSA_IP6}
+	log_test $? 0 "UDP in - LLA to GUA"
+
+	run_cmd_nsb ip -6 ro del ${NSA_IP6}/128 dev ${NSB_DEV}
+	run_cmd_nsb ip -6 addr add ${NSB_IP6}/64 dev ${NSB_DEV} nodad
+}
+
+ipv6_udp_vrf()
+{
+	local a
+
+	# disable global server
+	log_subsection "Global server disabled"
+	set_sysctl net.ipv4.udp_l3mdev_accept=0
+
+	#
+	# server tests
+	#
+	for a in ${NSA_IP6} ${VRF_IP6}
+	do
+		log_start
+		show_hint "Should fail 'Connection refused' since global server is disabled"
+		run_cmd nettest -6 -D -s &
+		sleep 1
+		run_cmd_nsb nettest -6 -D -r ${a}
+		log_test_addr ${a} $? 1 "Global server"
+	done
+
+	for a in ${NSA_IP6} ${VRF_IP6}
+	do
+		log_start
+		run_cmd nettest -6 -D -d ${VRF} -s -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd_nsb nettest -6 -D -r ${a}
+		log_test_addr ${a} $? 0 "VRF server"
+	done
+
+	for a in ${NSA_IP6} ${VRF_IP6}
+	do
+		log_start
+		run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd_nsb nettest -6 -D -r ${a}
+		log_test_addr ${a} $? 0 "Enslaved device server"
+	done
+
+	# negative test - should fail
+	for a in ${NSA_IP6} ${VRF_IP6}
+	do
+		log_start
+		show_hint "Should fail 'Connection refused' since there is no server"
+		run_cmd_nsb nettest -6 -D -r ${a}
+		log_test_addr ${a} $? 1 "No server"
+	done
+
+	#
+	# local address tests
+	#
+	for a in ${NSA_IP6} ${VRF_IP6}
+	do
+		log_start
+		show_hint "Should fail 'Connection refused' since global server is disabled"
+		run_cmd nettest -6 -D -s &
+		sleep 1
+		run_cmd nettest -6 -D -d ${VRF} -r ${a}
+		log_test_addr ${a} $? 1 "Global server, VRF client, local conn"
+	done
+
+	for a in ${NSA_IP6} ${VRF_IP6}
+	do
+		log_start
+		run_cmd nettest -6 -D -d ${VRF} -s &
+		sleep 1
+		run_cmd nettest -6 -D -d ${VRF} -r ${a}
+		log_test_addr ${a} $? 0 "VRF server, VRF client, local conn"
+	done
+
+	a=${NSA_IP6}
+	log_start
+	show_hint "Should fail 'Connection refused' since global server is disabled"
+	run_cmd nettest -6 -D -s &
+	sleep 1
+	run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a}
+	log_test_addr ${a} $? 1 "Global server, device client, local conn"
+
+	log_start
+	run_cmd nettest -6 -D -d ${VRF} -s -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a}
+	log_test_addr ${a} $? 0 "VRF server, device client, local conn"
+
+	log_start
+	run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -6 -D -d ${VRF} -r ${a}
+	log_test_addr ${a} $? 0 "Enslaved device server, VRF client, local conn"
+
+	log_start
+	run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a}
+	log_test_addr ${a} $? 0 "Enslaved device server, device client, local conn"
+
+	# disable global server
+	log_subsection "Global server enabled"
+	set_sysctl net.ipv4.udp_l3mdev_accept=1
+
+	#
+	# server tests
+	#
+	for a in ${NSA_IP6} ${VRF_IP6}
+	do
+		log_start
+		run_cmd nettest -6 -D -s -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd_nsb nettest -6 -D -r ${a}
+		log_test_addr ${a} $? 0 "Global server"
+	done
+
+	for a in ${NSA_IP6} ${VRF_IP6}
+	do
+		log_start
+		run_cmd nettest -6 -D -d ${VRF} -s -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd_nsb nettest -6 -D -r ${a}
+		log_test_addr ${a} $? 0 "VRF server"
+	done
+
+	for a in ${NSA_IP6} ${VRF_IP6}
+	do
+		log_start
+		run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd_nsb nettest -6 -D -r ${a}
+		log_test_addr ${a} $? 0 "Enslaved device server"
+	done
+
+	# negative test - should fail
+	for a in ${NSA_IP6} ${VRF_IP6}
+	do
+		log_start
+		run_cmd_nsb nettest -6 -D -r ${a}
+		log_test_addr ${a} $? 1 "No server"
+	done
+
+	#
+	# client tests
+	#
+	log_start
+	run_cmd_nsb nettest -6 -D -s &
+	sleep 1
+	run_cmd nettest -6 -D -d ${VRF} -r ${NSB_IP6}
+	log_test $? 0 "VRF client"
+
+	# negative test - should fail
+	log_start
+	run_cmd nettest -6 -D -d ${VRF} -r ${NSB_IP6}
+	log_test $? 1 "No server, VRF client"
+
+	log_start
+	run_cmd_nsb nettest -6 -D -s &
+	sleep 1
+	run_cmd nettest -6 -D -d ${NSA_DEV} -r ${NSB_IP6}
+	log_test $? 0 "Enslaved device client"
+
+	# negative test - should fail
+	log_start
+	run_cmd nettest -6 -D -d ${NSA_DEV} -r ${NSB_IP6}
+	log_test $? 1 "No server, enslaved device client"
+
+	#
+	# local address tests
+	#
+	a=${NSA_IP6}
+	log_start
+	run_cmd nettest -6 -D -s -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -6 -D -d ${VRF} -r ${a}
+	log_test_addr ${a} $? 0 "Global server, VRF client, local conn"
+
+	#log_start
+	run_cmd nettest -6 -D -d ${VRF} -s -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -6 -D -d ${VRF} -r ${a}
+	log_test_addr ${a} $? 0 "VRF server, VRF client, local conn"
+
+
+	a=${VRF_IP6}
+	log_start
+	run_cmd nettest -6 -D -s -2 ${VRF} &
+	sleep 1
+	run_cmd nettest -6 -D -d ${VRF} -r ${a}
+	log_test_addr ${a} $? 0 "Global server, VRF client, local conn"
+
+	log_start
+	run_cmd nettest -6 -D -d ${VRF} -s -2 ${VRF} &
+	sleep 1
+	run_cmd nettest -6 -D -d ${VRF} -r ${a}
+	log_test_addr ${a} $? 0 "VRF server, VRF client, local conn"
+
+	# negative test - should fail
+	for a in ${NSA_IP6} ${VRF_IP6}
+	do
+		log_start
+		run_cmd nettest -6 -D -d ${VRF} -r ${a}
+		log_test_addr ${a} $? 1 "No server, VRF client, local conn"
+	done
+
+	# device to global IP
+	a=${NSA_IP6}
+	log_start
+	run_cmd nettest -6 -D -s -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a}
+	log_test_addr ${a} $? 0 "Global server, device client, local conn"
+
+	log_start
+	run_cmd nettest -6 -D -d ${VRF} -s -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a}
+	log_test_addr ${a} $? 0 "VRF server, device client, local conn"
+
+	log_start
+	run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -6 -D -d ${VRF} -r ${a}
+	log_test_addr ${a} $? 0 "Device server, VRF client, local conn"
+
+	log_start
+	run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a}
+	log_test_addr ${a} $? 0 "Device server, device client, local conn"
+
+	log_start
+	run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a}
+	log_test_addr ${a} $? 1 "No server, device client, local conn"
+
+
+	# link local addresses
+	log_start
+	run_cmd nettest -6 -D -s &
+	sleep 1
+	run_cmd_nsb nettest -6 -D -d ${NSB_DEV} -r ${NSA_LINKIP6}
+	log_test $? 0 "Global server, linklocal IP"
+
+	log_start
+	run_cmd_nsb nettest -6 -D -d ${NSB_DEV} -r ${NSA_LINKIP6}
+	log_test $? 1 "No server, linklocal IP"
+
+
+	log_start
+	run_cmd_nsb nettest -6 -D -s &
+	sleep 1
+	run_cmd nettest -6 -D -d ${NSA_DEV} -r ${NSB_LINKIP6}
+	log_test $? 0 "Enslaved device client, linklocal IP"
+
+	log_start
+	run_cmd nettest -6 -D -d ${NSA_DEV} -r ${NSB_LINKIP6}
+	log_test $? 1 "No server, device client, peer linklocal IP"
+
+
+	log_start
+	run_cmd nettest -6 -D -s &
+	sleep 1
+	run_cmd nettest -6 -D -d ${NSA_DEV} -r ${NSA_LINKIP6}
+	log_test $? 0 "Enslaved device client, local conn - linklocal IP"
+
+	log_start
+	run_cmd nettest -6 -D -d ${NSA_DEV} -r ${NSA_LINKIP6}
+	log_test $? 1 "No server, device client, local conn  - linklocal IP"
+
+	# LLA to GUA
+	run_cmd_nsb ip -6 addr del ${NSB_IP6}/64 dev ${NSB_DEV}
+	run_cmd_nsb ip -6 ro add ${NSA_IP6}/128 dev ${NSB_DEV}
+	log_start
+	run_cmd nettest -6 -s -D &
+	sleep 1
+	run_cmd_nsb nettest -6 -D -r ${NSA_IP6}
+	log_test $? 0 "UDP in - LLA to GUA"
+
+	run_cmd_nsb ip -6 ro del ${NSA_IP6}/128 dev ${NSB_DEV}
+	run_cmd_nsb ip -6 addr add ${NSB_IP6}/64 dev ${NSB_DEV} nodad
+}
+
+ipv6_udp()
+{
+        # should not matter, but set to known state
+        set_sysctl net.ipv4.udp_early_demux=1
+
+        log_section "IPv6/UDP"
+        log_subsection "No VRF"
+        setup
+
+        # udp_l3mdev_accept should have no affect without VRF;
+        # run tests with it enabled and disabled to verify
+        log_subsection "udp_l3mdev_accept disabled"
+        set_sysctl net.ipv4.udp_l3mdev_accept=0
+        ipv6_udp_novrf
+        log_subsection "udp_l3mdev_accept enabled"
+        set_sysctl net.ipv4.udp_l3mdev_accept=1
+        ipv6_udp_novrf
+
+        log_subsection "With VRF"
+        setup "yes"
+        ipv6_udp_vrf
+}
+
+################################################################################
 # usage
 
 usage()
@@ -2069,7 +2558,7 @@ EOF
 # main
 
 TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp"
-TESTS_IPV6="ipv6_ping ipv6_tcp"
+TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp"
 PAUSE_ON_FAIL=no
 PAUSE=no
 
@@ -2113,6 +2602,7 @@ do
 
 	ipv6_ping|ping6) ipv6_ping;;
 	ipv6_tcp|tcp6)   ipv6_tcp;;
+	ipv6_udp|udp6)   ipv6_udp;;
 
 	# setup namespaces and config, but do not run any tests
 	setup)		 setup; exit 0;;
-- 
2.11.0


^ permalink raw reply related

* [PATCH net-next 09/15] selftests: Add ipv4 address bind tests to fcnal-test
From: David Ahern @ 2019-08-01 18:56 UTC (permalink / raw)
  To: davem; +Cc: netdev, David Ahern
In-Reply-To: <20190801185648.27653-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Add address bind tests to fcnal-test.sh. Verifies socket binding to
local addresses for raw, tcp and udp including device and VRF cases.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 tools/testing/selftests/net/fcnal-test.sh | 111 +++++++++++++++++++++++++++++-
 1 file changed, 110 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh
index 2a2e692bc242..6023ee1c6980 100755
--- a/tools/testing/selftests/net/fcnal-test.sh
+++ b/tools/testing/selftests/net/fcnal-test.sh
@@ -1401,6 +1401,114 @@ ipv4_udp()
 }
 
 ################################################################################
+# IPv4 address bind
+#
+# verifies ability or inability to bind to an address / device
+
+ipv4_addr_bind_novrf()
+{
+	#
+	# raw socket
+	#
+	for a in ${NSA_IP} ${NSA_LO_IP}
+	do
+		log_start
+		run_cmd nettest -s -R -P icmp -l ${a} -b
+		log_test_addr ${a} $? 0 "Raw socket bind to local address"
+
+		log_start
+		run_cmd nettest -s -R -P icmp -l ${a} -d ${NSA_DEV} -b
+		log_test_addr ${a} $? 0 "Raw socket bind to local address after device bind"
+	done
+
+	#
+	# tcp sockets
+	#
+	a=${NSA_IP}
+	log_start
+	run_cmd nettest -l ${a} -r ${NSB_IP} -t1 -b
+	log_test_addr ${a} $? 0 "TCP socket bind to local address"
+
+	log_start
+	run_cmd nettest -l ${a} -r ${NSB_IP} -d ${NSA_DEV} -t1 -b
+	log_test_addr ${a} $? 0 "TCP socket bind to local address after device bind"
+
+	# Sadly, the kernel allows binding a socket to a device and then
+	# binding to an address not on the device. The only restriction
+	# is that the address is valid in the L3 domain. So this test
+	# passes when it really should not
+	#a=${NSA_LO_IP}
+	#log_start
+	#show_hint "Should fail with 'Cannot assign requested address'"
+	#run_cmd nettest -s -l ${a} -d ${NSA_DEV} -t1 -b
+	#log_test_addr ${a} $? 1 "TCP socket bind to out of scope local address"
+}
+
+ipv4_addr_bind_vrf()
+{
+	#
+	# raw socket
+	#
+	for a in ${NSA_IP} ${VRF_IP}
+	do
+		log_start
+		run_cmd nettest -s -R -P icmp -l ${a} -b
+		log_test_addr ${a} $? 0 "Raw socket bind to local address"
+
+		log_start
+		run_cmd nettest -s -R -P icmp -l ${a} -d ${NSA_DEV} -b
+		log_test_addr ${a} $? 0 "Raw socket bind to local address after device bind"
+		log_start
+		run_cmd nettest -s -R -P icmp -l ${a} -d ${VRF} -b
+		log_test_addr ${a} $? 0 "Raw socket bind to local address after VRF bind"
+	done
+
+	a=${NSA_LO_IP}
+	log_start
+	show_hint "Address on loopback is out of VRF scope"
+	run_cmd nettest -s -R -P icmp -l ${a} -d ${VRF} -b
+	log_test_addr ${a} $? 1 "Raw socket bind to out of scope address after VRF bind"
+
+	#
+	# tcp sockets
+	#
+	for a in ${NSA_IP} ${VRF_IP}
+	do
+		log_start
+		run_cmd nettest -s -l ${a} -d ${VRF} -t1 -b
+		log_test_addr ${a} $? 0 "TCP socket bind to local address"
+
+		log_start
+		run_cmd nettest -s -l ${a} -d ${NSA_DEV} -t1 -b
+		log_test_addr ${a} $? 0 "TCP socket bind to local address after device bind"
+	done
+
+	a=${NSA_LO_IP}
+	log_start
+	show_hint "Address on loopback out of scope for VRF"
+	run_cmd nettest -s -l ${a} -d ${VRF} -t1 -b
+	log_test_addr ${a} $? 1 "TCP socket bind to invalid local address for VRF"
+
+	log_start
+	show_hint "Address on loopback out of scope for device in VRF"
+	run_cmd nettest -s -l ${a} -d ${NSA_DEV} -t1 -b
+	log_test_addr ${a} $? 1 "TCP socket bind to invalid local address for device bind"
+}
+
+ipv4_addr_bind()
+{
+	log_section "IPv4 address binds"
+
+	log_subsection "No VRF"
+	setup
+	ipv4_addr_bind_novrf
+
+	log_subsection "With VRF"
+	setup "yes"
+	ipv4_addr_bind_vrf
+}
+
+################################################################################
 # IPv6
 
 ipv6_ping_novrf()
@@ -2557,7 +2665,7 @@ EOF
 ################################################################################
 # main
 
-TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp"
+TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind"
 TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp"
 PAUSE_ON_FAIL=no
 PAUSE=no
@@ -2599,6 +2707,7 @@ do
 	ipv4_ping|ping)  ipv4_ping;;
 	ipv4_tcp|tcp)    ipv4_tcp;;
 	ipv4_udp|udp)    ipv4_udp;;
+	ipv4_bind|bind)  ipv4_addr_bind;;
 
 	ipv6_ping|ping6) ipv6_ping;;
 	ipv6_tcp|tcp6)   ipv6_tcp;;
-- 
2.11.0


^ permalink raw reply related

* [PATCH net-next 02/15] selftests: Setup for functional tests for fib and socket lookups
From: David Ahern @ 2019-08-01 18:56 UTC (permalink / raw)
  To: davem; +Cc: netdev, David Ahern
In-Reply-To: <20190801185648.27653-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Initial commit for functional test suite for fib and socket lookups.
This commit contains the namespace setup, networking config, test options
and other basic infrastructure.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 tools/testing/selftests/net/Makefile      |   2 +-
 tools/testing/selftests/net/fcnal-test.sh | 520 ++++++++++++++++++++++++++++++
 2 files changed, 521 insertions(+), 1 deletion(-)
 create mode 100755 tools/testing/selftests/net/fcnal-test.sh

diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index ba9ee36c9e94..70f2d6656170 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -10,7 +10,7 @@ TEST_PROGS += fib_tests.sh fib-onlink-tests.sh pmtu.sh udpgso.sh ip_defrag.sh
 TEST_PROGS += udpgso_bench.sh fib_rule_tests.sh msg_zerocopy.sh psock_snd.sh
 TEST_PROGS += udpgro_bench.sh udpgro.sh test_vxlan_under_vrf.sh reuseport_addr_any.sh
 TEST_PROGS += test_vxlan_fdb_changelink.sh so_txtime.sh ipv6_flowlabel.sh
-TEST_PROGS += tcp_fastopen_backup_key.sh
+TEST_PROGS += tcp_fastopen_backup_key.sh fcnal-test.sh
 TEST_PROGS_EXTENDED := in_netns.sh
 TEST_GEN_FILES =  socket nettest
 TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy reuseport_addr_any
diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh
new file mode 100755
index 000000000000..22cfbd2fd09c
--- /dev/null
+++ b/tools/testing/selftests/net/fcnal-test.sh
@@ -0,0 +1,520 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) 2019 David Ahern <dsahern@gmail.com>. All rights reserved.
+#
+# IPv4 and IPv6 functional tests focusing on VRF and routing lookups
+# for various permutations:
+#   1. icmp, tcp, udp and netfilter
+#   2. client, server, no-server
+#   3. global address on interface
+#   4. global address on 'lo'
+#   5. remote and local traffic
+#   6. VRF and non-VRF permutations
+#
+# Setup:
+#                     ns-A     |     ns-B
+# No VRF case:
+#    [ lo ]         [ eth1 ]---|---[ eth1 ]      [ lo ]
+#                                                remote address
+# VRF case:
+#         [ red ]---[ eth1 ]---|---[ eth1 ]      [ lo ]
+#
+# ns-A:
+#     eth1: 172.16.1.1/24, 2001:db8:1::1/64
+#       lo: 127.0.0.1/8, ::1/128
+#           172.16.2.1/32, 2001:db8:2::1/128
+#      red: 127.0.0.1/8, ::1/128
+#           172.16.3.1/32, 2001:db8:3::1/128
+#
+# ns-B:
+#     eth1: 172.16.1.2/24, 2001:db8:1::2/64
+#      lo2: 127.0.0.1/8, ::1/128
+#           172.16.2.2/32, 2001:db8:2::2/128
+#
+# server / client nomenclature relative to ns-A
+
+VERBOSE=0
+
+NSA_DEV=eth1
+NSB_DEV=eth1
+VRF=red
+VRF_TABLE=1101
+
+# IPv4 config
+NSA_IP=172.16.1.1
+NSB_IP=172.16.1.2
+VRF_IP=172.16.3.1
+
+# IPv6 config
+NSA_IP6=2001:db8:1::1
+NSB_IP6=2001:db8:1::2
+VRF_IP6=2001:db8:3::1
+
+NSA_LO_IP=172.16.2.1
+NSB_LO_IP=172.16.2.2
+NSA_LO_IP6=2001:db8:2::1
+NSB_LO_IP6=2001:db8:2::2
+
+MCAST=ff02::1
+# set after namespace create
+NSA_LINKIP6=
+NSB_LINKIP6=
+
+NSA=ns-A
+NSB=ns-B
+
+NSA_CMD="ip netns exec ${NSA}"
+NSB_CMD="ip netns exec ${NSB}"
+
+which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping)
+
+################################################################################
+# utilities
+
+log_test()
+{
+	local rc=$1
+	local expected=$2
+	local msg="$3"
+
+	[ "${VERBOSE}" = "1" ] && echo
+
+	if [ ${rc} -eq ${expected} ]; then
+		nsuccess=$((nsuccess+1))
+		printf "TEST: %-70s  [ OK ]\n" "${msg}"
+	else
+		nfail=$((nfail+1))
+		printf "TEST: %-70s  [FAIL]\n" "${msg}"
+		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
+			echo
+			echo "hit enter to continue, 'q' to quit"
+			read a
+			[ "$a" = "q" ] && exit 1
+		fi
+	fi
+
+	if [ "${PAUSE}" = "yes" ]; then
+		echo
+		echo "hit enter to continue, 'q' to quit"
+		read a
+		[ "$a" = "q" ] && exit 1
+	fi
+
+	kill_procs
+}
+
+log_test_addr()
+{
+	local addr=$1
+	local rc=$2
+	local expected=$3
+	local msg="$4"
+	local astr
+
+	astr=$(addr2str ${addr})
+	log_test $rc $expected "$msg - ${astr}"
+}
+
+log_section()
+{
+	echo
+	echo "###########################################################################"
+	echo "$*"
+	echo "###########################################################################"
+	echo
+}
+
+log_subsection()
+{
+	echo
+	echo "#################################################################"
+	echo "$*"
+	echo
+}
+
+log_start()
+{
+	# make sure we have no test instances running
+	kill_procs
+
+	if [ "${VERBOSE}" = "1" ]; then
+		echo
+		echo "#######################################################"
+	fi
+}
+
+log_debug()
+{
+	if [ "${VERBOSE}" = "1" ]; then
+		echo
+		echo "$*"
+		echo
+	fi
+}
+
+show_hint()
+{
+	if [ "${VERBOSE}" = "1" ]; then
+		echo "HINT: $*"
+		echo
+	fi
+}
+
+kill_procs()
+{
+	killall nettest ping ping6 >/dev/null 2>&1
+	sleep 1
+}
+
+do_run_cmd()
+{
+	local cmd="$*"
+	local out
+
+	if [ "$VERBOSE" = "1" ]; then
+		echo "COMMAND: ${cmd}"
+	fi
+
+	out=$($cmd 2>&1)
+	rc=$?
+	if [ "$VERBOSE" = "1" -a -n "$out" ]; then
+		echo "$out"
+	fi
+
+	return $rc
+}
+
+run_cmd()
+{
+	do_run_cmd ${NSA_CMD} $*
+}
+
+run_cmd_nsb()
+{
+	do_run_cmd ${NSB_CMD} $*
+}
+
+setup_cmd()
+{
+	local cmd="$*"
+	local rc
+
+	run_cmd ${cmd}
+	rc=$?
+	if [ $rc -ne 0 ]; then
+		# show user the command if not done so already
+		if [ "$VERBOSE" = "0" ]; then
+			echo "setup command: $cmd"
+		fi
+		echo "failed. stopping tests"
+		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
+			echo
+			echo "hit enter to continue"
+			read a
+		fi
+		exit $rc
+	fi
+}
+
+setup_cmd_nsb()
+{
+	local cmd="$*"
+	local rc
+
+	run_cmd_nsb ${cmd}
+	rc=$?
+	if [ $rc -ne 0 ]; then
+		# show user the command if not done so already
+		if [ "$VERBOSE" = "0" ]; then
+			echo "setup command: $cmd"
+		fi
+		echo "failed. stopping tests"
+		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
+			echo
+			echo "hit enter to continue"
+			read a
+		fi
+		exit $rc
+	fi
+}
+
+# set sysctl values in NS-A
+set_sysctl()
+{
+	echo "SYSCTL: $*"
+	echo
+	run_cmd sysctl -q -w $*
+}
+
+################################################################################
+# Setup for tests
+
+addr2str()
+{
+	case "$1" in
+	127.0.0.1) echo "loopback";;
+	::1) echo "IPv6 loopback";;
+
+	${NSA_IP})	echo "ns-A IP";;
+	${NSA_IP6})	echo "ns-A IPv6";;
+	${NSA_LO_IP})	echo "ns-A loopback IP";;
+	${NSA_LO_IP6})	echo "ns-A loopback IPv6";;
+	${NSA_LINKIP6}|${NSA_LINKIP6}%*) echo "ns-A IPv6 LLA";;
+
+	${NSB_IP})	echo "ns-B IP";;
+	${NSB_IP6})	echo "ns-B IPv6";;
+	${NSB_LO_IP})	echo "ns-B loopback IP";;
+	${NSB_LO_IP6})	echo "ns-B loopback IPv6";;
+	${NSB_LINKIP6}|${NSB_LINKIP6}%*) echo "ns-B IPv6 LLA";;
+
+	${VRF_IP})	echo "VRF IP";;
+	${VRF_IP6})	echo "VRF IPv6";;
+
+	${MCAST}%*)	echo "multicast IP";;
+
+	*) echo "unknown";;
+	esac
+}
+
+get_linklocal()
+{
+	local ns=$1
+	local dev=$2
+	local addr
+
+	addr=$(ip -netns ${ns} -6 -br addr show dev ${dev} | \
+	awk '{
+		for (i = 3; i <= NF; ++i) {
+			if ($i ~ /^fe80/)
+				print $i
+		}
+	}'
+	)
+	addr=${addr/\/*}
+
+	[ -z "$addr" ] && return 1
+
+	echo $addr
+
+	return 0
+}
+
+################################################################################
+# create namespaces and vrf
+
+create_vrf()
+{
+	local ns=$1
+	local vrf=$2
+	local table=$3
+	local addr=$4
+	local addr6=$5
+
+	ip -netns ${ns} link add ${vrf} type vrf table ${table}
+	ip -netns ${ns} link set ${vrf} up
+	ip -netns ${ns} route add vrf ${vrf} unreachable default metric 8192
+	ip -netns ${ns} -6 route add vrf ${vrf} unreachable default metric 8192
+
+	ip -netns ${ns} addr add 127.0.0.1/8 dev ${vrf}
+	ip -netns ${ns} -6 addr add ::1 dev ${vrf} nodad
+	if [ "${addr}" != "-" ]; then
+		ip -netns ${ns} addr add dev ${vrf} ${addr}
+	fi
+	if [ "${addr6}" != "-" ]; then
+		ip -netns ${ns} -6 addr add dev ${vrf} ${addr6}
+	fi
+
+	ip -netns ${ns} ru del pref 0
+	ip -netns ${ns} ru add pref 32765 from all lookup local
+	ip -netns ${ns} -6 ru del pref 0
+	ip -netns ${ns} -6 ru add pref 32765 from all lookup local
+}
+
+create_ns()
+{
+	local ns=$1
+	local addr=$2
+	local addr6=$3
+
+	ip netns add ${ns}
+
+	ip -netns ${ns} link set lo up
+	if [ "${addr}" != "-" ]; then
+		ip -netns ${ns} addr add dev lo ${addr}
+	fi
+	if [ "${addr6}" != "-" ]; then
+		ip -netns ${ns} -6 addr add dev lo ${addr6}
+	fi
+
+	ip -netns ${ns} ro add unreachable default metric 8192
+	ip -netns ${ns} -6 ro add unreachable default metric 8192
+
+	ip netns exec ${ns} sysctl -qw net.ipv4.ip_forward=1
+	ip netns exec ${ns} sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1
+	ip netns exec ${ns} sysctl -qw net.ipv6.conf.all.forwarding=1
+	ip netns exec ${ns} sysctl -qw net.ipv6.conf.default.forwarding=1
+}
+
+# create veth pair to connect namespaces and apply addresses.
+connect_ns()
+{
+	local ns1=$1
+	local ns1_dev=$2
+	local ns1_addr=$3
+	local ns1_addr6=$4
+	local ns2=$5
+	local ns2_dev=$6
+	local ns2_addr=$7
+	local ns2_addr6=$8
+
+	ip -netns ${ns1} li add ${ns1_dev} type veth peer name tmp
+	ip -netns ${ns1} li set ${ns1_dev} up
+	ip -netns ${ns1} li set tmp netns ${ns2} name ${ns2_dev}
+	ip -netns ${ns2} li set ${ns2_dev} up
+
+	if [ "${ns1_addr}" != "-" ]; then
+		ip -netns ${ns1} addr add dev ${ns1_dev} ${ns1_addr}
+		ip -netns ${ns2} addr add dev ${ns2_dev} ${ns2_addr}
+	fi
+
+	if [ "${ns1_addr6}" != "-" ]; then
+		ip -netns ${ns1} addr add dev ${ns1_dev} ${ns1_addr6}
+		ip -netns ${ns2} addr add dev ${ns2_dev} ${ns2_addr6}
+	fi
+}
+
+cleanup()
+{
+	# explicit cleanups to check those code paths
+	ip netns | grep -q ${NSA}
+	if [ $? -eq 0 ]; then
+		ip -netns ${NSA} link delete ${VRF}
+		ip -netns ${NSA} ro flush table ${VRF_TABLE}
+
+		ip -netns ${NSA} addr flush dev ${NSA_DEV}
+		ip -netns ${NSA} -6 addr flush dev ${NSA_DEV}
+		ip -netns ${NSA} link set dev ${NSA_DEV} down
+		ip -netns ${NSA} link del dev ${NSA_DEV}
+
+		ip netns del ${NSA}
+	fi
+
+	ip netns del ${NSB}
+}
+
+setup()
+{
+	local with_vrf=${1}
+
+	# make sure we are starting with a clean slate
+	kill_procs
+	cleanup 2>/dev/null
+
+	log_debug "Configuring network namespaces"
+	set -e
+
+	create_ns ${NSA} ${NSA_LO_IP}/32 ${NSA_LO_IP6}/128
+	create_ns ${NSB} ${NSB_LO_IP}/32 ${NSB_LO_IP6}/128
+	connect_ns ${NSA} ${NSA_DEV} ${NSA_IP}/24 ${NSA_IP6}/64 \
+		   ${NSB} ${NSB_DEV} ${NSB_IP}/24 ${NSB_IP6}/64
+
+	NSA_LINKIP6=$(get_linklocal ${NSA} ${NSA_DEV})
+	NSB_LINKIP6=$(get_linklocal ${NSB} ${NSB_DEV})
+
+	# tell ns-A how to get to remote addresses of ns-B
+	if [ "${with_vrf}" = "yes" ]; then
+		create_vrf ${NSA} ${VRF} ${VRF_TABLE} ${VRF_IP} ${VRF_IP6}
+
+		ip -netns ${NSA} link set dev ${NSA_DEV} vrf ${VRF}
+		ip -netns ${NSA} ro add vrf ${VRF} ${NSB_LO_IP}/32 via ${NSB_IP} dev ${NSA_DEV}
+		ip -netns ${NSA} -6 ro add vrf ${VRF} ${NSB_LO_IP6}/128 via ${NSB_IP6} dev ${NSA_DEV}
+
+		ip -netns ${NSB} ro add ${VRF_IP}/32 via ${NSA_IP} dev ${NSB_DEV}
+		ip -netns ${NSB} -6 ro add ${VRF_IP6}/128 via ${NSA_IP6} dev ${NSB_DEV}
+	else
+		ip -netns ${NSA} ro add ${NSB_LO_IP}/32 via ${NSB_IP} dev ${NSA_DEV}
+		ip -netns ${NSA} ro add ${NSB_LO_IP6}/128 via ${NSB_IP6} dev ${NSA_DEV}
+	fi
+
+
+	# tell ns-B how to get to remote addresses of ns-A
+	ip -netns ${NSB} ro add ${NSA_LO_IP}/32 via ${NSA_IP} dev ${NSB_DEV}
+	ip -netns ${NSB} ro add ${NSA_LO_IP6}/128 via ${NSA_IP6} dev ${NSB_DEV}
+
+	set +e
+
+	sleep 1
+}
+
+################################################################################
+# usage
+
+usage()
+{
+	cat <<EOF
+usage: ${0##*/} OPTS
+
+	-4          IPv4 tests only
+	-6          IPv6 tests only
+	-t <test>   Test name/set to run
+	-p          Pause on fail
+	-P          Pause after each test
+	-v          Be verbose
+EOF
+}
+
+################################################################################
+# main
+
+TESTS_IPV4=""
+TESTS_IPV6=""
+PAUSE_ON_FAIL=no
+PAUSE=no
+
+while getopts :46t:pPvh o
+do
+	case $o in
+		4) TESTS=ipv4;;
+		6) TESTS=ipv6;;
+		t) TESTS=$OPTARG;;
+		p) PAUSE_ON_FAIL=yes;;
+		P) PAUSE=yes;;
+		v) VERBOSE=1;;
+		h) usage; exit 0;;
+		*) usage; exit 1;;
+	esac
+done
+
+# make sure we don't pause twice
+[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
+
+#
+# show user test config
+#
+if [ -z "$TESTS" ]; then
+	TESTS="$TESTS_IPV4 $TESTS_IPV6 $TESTS_OTHER"
+elif [ "$TESTS" = "ipv4" ]; then
+	TESTS="$TESTS_IPV4"
+elif [ "$TESTS" = "ipv6" ]; then
+	TESTS="$TESTS_IPV6"
+fi
+
+declare -i nfail=0
+declare -i nsuccess=0
+
+for t in $TESTS
+do
+	case $t in
+	# setup namespaces and config, but do not run any tests
+	setup)		 setup; exit 0;;
+	vrf_setup)	 setup "yes"; exit 0;;
+
+	help)            echo "Test names: $TESTS"; exit 0;;
+	esac
+done
+
+cleanup 2>/dev/null
+
+printf "\nTests passed: %3d\n" ${nsuccess}
+printf "Tests failed: %3d\n"   ${nfail}
-- 
2.11.0


^ permalink raw reply related

* [PATCH net-next 05/15] selftests: Add ipv4 tcp tests to fcnal-test
From: David Ahern @ 2019-08-01 18:56 UTC (permalink / raw)
  To: davem; +Cc: netdev, David Ahern
In-Reply-To: <20190801185648.27653-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Add tcp tests to fcnal-test.sh. Covers the permutations of directly
connected addresses, routed destinations, VRF and non-VRF, and expected
failures for both clients and servers. Includes permutations with
net.ipv4.tcp_l3mdev_accept set to 0 and 1.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 tools/testing/selftests/net/fcnal-test.sh | 315 +++++++++++++++++++++++++++++-
 1 file changed, 314 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh
index 4da510f6d625..f9e2f1464dcd 100755
--- a/tools/testing/selftests/net/fcnal-test.sh
+++ b/tools/testing/selftests/net/fcnal-test.sh
@@ -712,6 +712,317 @@ ipv4_ping()
 }
 
 ################################################################################
+# IPv4 TCP
+
+ipv4_tcp_novrf()
+{
+	local a
+
+	#
+	# server tests
+	#
+	for a in ${NSA_IP} ${NSA_LO_IP}
+	do
+		log_start
+		run_cmd nettest -s &
+		sleep 1
+		run_cmd_nsb nettest -r ${a}
+		log_test_addr ${a} $? 0 "Global server"
+	done
+
+	a=${NSA_IP}
+	log_start
+	run_cmd nettest -s -d ${NSA_DEV} &
+	sleep 1
+	run_cmd_nsb nettest -r ${a}
+	log_test_addr ${a} $? 0 "Device server"
+
+	# verify TCP reset sent and received
+	for a in ${NSA_IP} ${NSA_LO_IP}
+	do
+		log_start
+		show_hint "Should fail 'Connection refused' since there is no server"
+		run_cmd_nsb nettest -r ${a}
+		log_test_addr ${a} $? 1 "No server"
+	done
+
+	#
+	# client
+	#
+	for a in ${NSB_IP} ${NSB_LO_IP}
+	do
+		log_start
+		run_cmd_nsb nettest -s &
+		sleep 1
+		run_cmd nettest -r ${a} -0 ${NSA_IP}
+		log_test_addr ${a} $? 0 "Client"
+
+		log_start
+		run_cmd_nsb nettest -s &
+		sleep 1
+		run_cmd nettest -r ${a} -d ${NSA_DEV}
+		log_test_addr ${a} $? 0 "Client, device bind"
+
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd nettest -r ${a}
+		log_test_addr ${a} $? 1 "No server, unbound client"
+
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd nettest -r ${a} -d ${NSA_DEV}
+		log_test_addr ${a} $? 1 "No server, device client"
+	done
+
+	#
+	# local address tests
+	#
+	for a in ${NSA_IP} ${NSA_LO_IP} 127.0.0.1
+	do
+		log_start
+		run_cmd nettest -s &
+		sleep 1
+		run_cmd nettest -r ${a} -0 ${a} -1 ${a}
+		log_test_addr ${a} $? 0 "Global server, local connection"
+	done
+
+	a=${NSA_IP}
+	log_start
+	run_cmd nettest -s -d ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -r ${a} -0 ${a}
+	log_test_addr ${a} $? 0 "Device server, unbound client, local connection"
+
+	for a in ${NSA_LO_IP} 127.0.0.1
+	do
+		log_start
+		show_hint "Should fail 'Connection refused' since addresses on loopback are out of device scope"
+		run_cmd nettest -s -d ${NSA_DEV} &
+		sleep 1
+		run_cmd nettest -r ${a}
+		log_test_addr ${a} $? 1 "Device server, unbound client, local connection"
+	done
+
+	a=${NSA_IP}
+	log_start
+	run_cmd nettest -s &
+	sleep 1
+	run_cmd nettest -r ${a} -0 ${a} -d ${NSA_DEV}
+	log_test_addr ${a} $? 0 "Global server, device client, local connection"
+
+	for a in ${NSA_LO_IP} 127.0.0.1
+	do
+		log_start
+		show_hint "Should fail 'No route to host' since addresses on loopback are out of device scope"
+		run_cmd nettest -s &
+		sleep 1
+		run_cmd nettest -r ${a} -d ${NSA_DEV}
+		log_test_addr ${a} $? 1 "Global server, device client, local connection"
+	done
+
+	a=${NSA_IP}
+	log_start
+	run_cmd nettest -s -d ${NSA_DEV} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest  -d ${NSA_DEV} -r ${a} -0 ${a}
+	log_test_addr ${a} $? 0 "Device server, device client, local connection"
+
+	log_start
+	show_hint "Should fail 'Connection refused'"
+	run_cmd nettest -d ${NSA_DEV} -r ${a}
+	log_test_addr ${a} $? 1 "No server, device client, local conn"
+}
+
+ipv4_tcp_vrf()
+{
+	local a
+
+	# disable global server
+	log_subsection "Global server disabled"
+
+	set_sysctl net.ipv4.tcp_l3mdev_accept=0
+
+	#
+	# server tests
+	#
+	for a in ${NSA_IP} ${VRF_IP}
+	do
+		log_start
+		show_hint "Should fail 'Connection refused' since global server with VRF is disabled"
+		run_cmd nettest -s &
+		sleep 1
+		run_cmd_nsb nettest -r ${a}
+		log_test_addr ${a} $? 1 "Global server"
+
+		log_start
+		run_cmd nettest -s -d ${VRF} -2 ${VRF} &
+		sleep 1
+		run_cmd_nsb nettest -r ${a}
+		log_test_addr ${a} $? 0 "VRF server"
+
+		log_start
+		run_cmd nettest -s -d ${NSA_DEV} -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd_nsb nettest -r ${a}
+		log_test_addr ${a} $? 0 "Device server"
+
+		# verify TCP reset received
+		log_start
+		show_hint "Should fail 'Connection refused' since there is no server"
+		run_cmd_nsb nettest -r ${a}
+		log_test_addr ${a} $? 1 "No server"
+	done
+
+	# local address tests
+	# (${VRF_IP} and 127.0.0.1 both timeout)
+	a=${NSA_IP}
+	log_start
+	show_hint "Should fail 'Connection refused' since global server with VRF is disabled"
+	run_cmd nettest -s &
+	sleep 1
+	run_cmd nettest -r ${a} -d ${NSA_DEV}
+	log_test_addr ${a} $? 1 "Global server, local connection"
+
+	#
+	# enable VRF global server
+	#
+	log_subsection "VRF Global server enabled"
+	set_sysctl net.ipv4.tcp_l3mdev_accept=1
+
+	for a in ${NSA_IP} ${VRF_IP}
+	do
+		log_start
+		show_hint "client socket should be bound to VRF"
+		run_cmd nettest -s -2 ${VRF} &
+		sleep 1
+		run_cmd_nsb nettest -r ${a}
+		log_test_addr ${a} $? 0 "Global server"
+
+		log_start
+		show_hint "client socket should be bound to VRF"
+		run_cmd nettest -s -d ${VRF} -2 ${VRF} &
+		sleep 1
+		run_cmd_nsb nettest -r ${a}
+		log_test_addr ${a} $? 0 "VRF server"
+
+		# verify TCP reset received
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd_nsb nettest -r ${a}
+		log_test_addr ${a} $? 1 "No server"
+	done
+
+	a=${NSA_IP}
+	log_start
+	show_hint "client socket should be bound to device"
+	run_cmd nettest -s -d ${NSA_DEV} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd_nsb nettest -r ${a}
+	log_test_addr ${a} $? 0 "Device server"
+
+	# local address tests
+	for a in ${NSA_IP} ${VRF_IP}
+	do
+		log_start
+		show_hint "Should fail 'No route to host' since client is not bound to VRF"
+		run_cmd nettest -s -2 ${VRF} &
+		sleep 1
+		run_cmd nettest -r ${a}
+		log_test_addr ${a} $? 1 "Global server, local connection"
+	done
+
+	#
+	# client
+	#
+	for a in ${NSB_IP} ${NSB_LO_IP}
+	do
+		log_start
+		run_cmd_nsb nettest -s &
+		sleep 1
+		run_cmd nettest -r ${a} -d ${VRF}
+		log_test_addr ${a} $? 0 "Client, VRF bind"
+
+		log_start
+		run_cmd_nsb nettest -s &
+		sleep 1
+		run_cmd nettest -r ${a} -d ${NSA_DEV}
+		log_test_addr ${a} $? 0 "Client, device bind"
+
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd nettest -r ${a} -d ${VRF}
+		log_test_addr ${a} $? 1 "No server, VRF client"
+
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd nettest -r ${a} -d ${NSA_DEV}
+		log_test_addr ${a} $? 1 "No server, device client"
+	done
+
+	for a in ${NSA_IP} ${VRF_IP} 127.0.0.1
+	do
+		log_start
+		run_cmd nettest -s -d ${VRF} -2 ${VRF} &
+		sleep 1
+		run_cmd nettest -r ${a} -d ${VRF} -0 ${a}
+		log_test_addr ${a} $? 0 "VRF server, VRF client, local connection"
+	done
+
+	a=${NSA_IP}
+	log_start
+	run_cmd nettest -s -d ${VRF} -2 ${VRF} &
+	sleep 1
+	run_cmd nettest -r ${a} -d ${NSA_DEV} -0 ${a}
+	log_test_addr ${a} $? 0 "VRF server, device client, local connection"
+
+	log_start
+	show_hint "Should fail 'No route to host' since client is out of VRF scope"
+	run_cmd nettest -s -d ${VRF} &
+	sleep 1
+	run_cmd nettest -r ${a}
+	log_test_addr ${a} $? 1 "VRF server, unbound client, local connection"
+
+	log_start
+	run_cmd nettest -s -d ${NSA_DEV} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -r ${a} -d ${VRF} -0 ${a}
+	log_test_addr ${a} $? 0 "Device server, VRF client, local connection"
+
+	log_start
+	run_cmd nettest -s -d ${NSA_DEV} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -r ${a} -d ${NSA_DEV} -0 ${a}
+	log_test_addr ${a} $? 0 "Device server, device client, local connection"
+}
+
+ipv4_tcp()
+{
+	log_section "IPv4/TCP"
+
+	which nettest >/dev/null
+	if [ $? -ne 0 ]; then
+		log_error "nettest not found; skipping tests"
+		return
+	fi
+
+	log_subsection "No VRF"
+	setup
+
+	# tcp_l3mdev_accept should have no affect without VRF;
+	# run tests with it enabled and disabled to verify
+	log_subsection "tcp_l3mdev_accept disabled"
+	set_sysctl net.ipv4.tcp_l3mdev_accept=0
+	ipv4_tcp_novrf
+	log_subsection "tcp_l3mdev_accept enabled"
+	set_sysctl net.ipv4.tcp_l3mdev_accept=1
+	ipv4_tcp_novrf
+
+	log_subsection "With VRF"
+	setup "yes"
+	ipv4_tcp_vrf
+}
+
+################################################################################
 # IPv6
 
 ipv6_ping_novrf()
@@ -1012,7 +1323,7 @@ EOF
 ################################################################################
 # main
 
-TESTS_IPV4="ipv4_ping"
+TESTS_IPV4="ipv4_ping ipv4_tcp"
 TESTS_IPV6="ipv6_ping"
 PAUSE_ON_FAIL=no
 PAUSE=no
@@ -1052,6 +1363,8 @@ for t in $TESTS
 do
 	case $t in
 	ipv4_ping|ping)  ipv4_ping;;
+	ipv4_tcp|tcp)    ipv4_tcp;;
+
 	ipv6_ping|ping6) ipv6_ping;;
 
 	# setup namespaces and config, but do not run any tests
-- 
2.11.0


^ permalink raw reply related

* [PATCH net-next 07/15] selftests: Add ipv4 udp tests to fcnal-test
From: David Ahern @ 2019-08-01 18:56 UTC (permalink / raw)
  To: davem; +Cc: netdev, David Ahern
In-Reply-To: <20190801185648.27653-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Add udp tests to fcnal-test.sh. Covers the permutations of directly
connected addresses, routed destinations, VRF and non-VRF, and expected
failures for both clients and servers. Includes permutations with
net.ipv4.udp_l3mdev_accept set to 0 and 1.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 tools/testing/selftests/net/fcnal-test.sh | 381 +++++++++++++++++++++++++++++-
 1 file changed, 380 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh
index 97291c6d17c5..afe9eb55d04a 100755
--- a/tools/testing/selftests/net/fcnal-test.sh
+++ b/tools/testing/selftests/net/fcnal-test.sh
@@ -1023,6 +1023,384 @@ ipv4_tcp()
 }
 
 ################################################################################
+# IPv4 UDP
+
+ipv4_udp_novrf()
+{
+	local a
+
+	#
+	# server tests
+	#
+	for a in ${NSA_IP} ${NSA_LO_IP}
+	do
+		log_start
+		run_cmd nettest -D -s -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd_nsb nettest -D -r ${a}
+		log_test_addr ${a} $? 0 "Global server"
+
+		log_start
+		show_hint "Should fail 'Connection refused' since there is no server"
+		run_cmd_nsb nettest -D -r ${a}
+		log_test_addr ${a} $? 1 "No server"
+	done
+
+	a=${NSA_IP}
+	log_start
+	run_cmd nettest -D -d ${NSA_DEV} -s -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd_nsb nettest -D -r ${a}
+	log_test_addr ${a} $? 0 "Device server"
+
+	#
+	# client
+	#
+	for a in ${NSB_IP} ${NSB_LO_IP}
+	do
+		log_start
+		run_cmd_nsb nettest -D -s &
+		sleep 1
+		run_cmd nettest -D -r ${a} -0 ${NSA_IP}
+		log_test_addr ${a} $? 0 "Client"
+
+		log_start
+		run_cmd_nsb nettest -D -s &
+		sleep 1
+		run_cmd nettest -D -r ${a} -d ${NSA_DEV} -0 ${NSA_IP}
+		log_test_addr ${a} $? 0 "Client, device bind"
+
+		log_start
+		run_cmd_nsb nettest -D -s &
+		sleep 1
+		run_cmd nettest -D -r ${a} -d ${NSA_DEV} -C -0 ${NSA_IP}
+		log_test_addr ${a} $? 0 "Client, device send via cmsg"
+
+		log_start
+		run_cmd_nsb nettest -D -s &
+		sleep 1
+		run_cmd nettest -D -r ${a} -d ${NSA_DEV} -S -0 ${NSA_IP}
+		log_test_addr ${a} $? 0 "Client, device bind via IP_UNICAST_IF"
+
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd nettest -D -r ${a}
+		log_test_addr ${a} $? 1 "No server, unbound client"
+
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd nettest -D -r ${a} -d ${NSA_DEV}
+		log_test_addr ${a} $? 1 "No server, device client"
+	done
+
+	#
+	# local address tests
+	#
+	for a in ${NSA_IP} ${NSA_LO_IP} 127.0.0.1
+	do
+		log_start
+		run_cmd nettest -D -s &
+		sleep 1
+		run_cmd nettest -D -r ${a} -0 ${a} -1 ${a}
+		log_test_addr ${a} $? 0 "Global server, local connection"
+	done
+
+	a=${NSA_IP}
+	log_start
+	run_cmd nettest -s -D -d ${NSA_DEV} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -D -r ${a}
+	log_test_addr ${a} $? 0 "Device server, unbound client, local connection"
+
+	for a in ${NSA_LO_IP} 127.0.0.1
+	do
+		log_start
+		show_hint "Should fail 'Connection refused' since address is out of device scope"
+		run_cmd nettest -s -D -d ${NSA_DEV} &
+		sleep 1
+		run_cmd nettest -D -r ${a}
+		log_test_addr ${a} $? 1 "Device server, unbound client, local connection"
+	done
+
+	a=${NSA_IP}
+	log_start
+	run_cmd nettest -s -D &
+	sleep 1
+	run_cmd nettest -D -d ${NSA_DEV} -r ${a}
+	log_test_addr ${a} $? 0 "Global server, device client, local connection"
+
+	log_start
+	run_cmd nettest -s -D &
+	sleep 1
+	run_cmd nettest -D -d ${NSA_DEV} -C -r ${a}
+	log_test_addr ${a} $? 0 "Global server, device send via cmsg, local connection"
+
+	log_start
+	run_cmd nettest -s -D &
+	sleep 1
+	run_cmd nettest -D -d ${NSA_DEV} -S -r ${a}
+	log_test_addr ${a} $? 0 "Global server, device client via IP_UNICAST_IF, local connection"
+
+	# IPv4 with device bind has really weird behavior - it overrides the
+	# fib lookup, generates an rtable and tries to send the packet. This
+	# causes failures for local traffic at different places
+	for a in ${NSA_LO_IP} 127.0.0.1
+	do
+		log_start
+		show_hint "Should fail since addresses on loopback are out of device scope"
+		run_cmd nettest -D -s &
+		sleep 1
+		run_cmd nettest -D -r ${a} -d ${NSA_DEV}
+		log_test_addr ${a} $? 2 "Global server, device client, local connection"
+
+		log_start
+		show_hint "Should fail since addresses on loopback are out of device scope"
+		run_cmd nettest -D -s &
+		sleep 1
+		run_cmd nettest -D -r ${a} -d ${NSA_DEV} -C
+		log_test_addr ${a} $? 1 "Global server, device send via cmsg, local connection"
+
+		log_start
+		show_hint "Should fail since addresses on loopback are out of device scope"
+		run_cmd nettest -D -s &
+		sleep 1
+		run_cmd nettest -D -r ${a} -d ${NSA_DEV} -S
+		log_test_addr ${a} $? 1 "Global server, device client via IP_UNICAST_IF, local connection"
+	done
+
+	a=${NSA_IP}
+	log_start
+	run_cmd nettest -D -s -d ${NSA_DEV} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -D -d ${NSA_DEV} -r ${a} -0 ${a}
+	log_test_addr ${a} $? 0 "Device server, device client, local conn"
+
+	log_start
+	run_cmd nettest -D -d ${NSA_DEV} -r ${a}
+	log_test_addr ${a} $? 2 "No server, device client, local conn"
+}
+
+ipv4_udp_vrf()
+{
+	local a
+
+	# disable global server
+	log_subsection "Global server disabled"
+	set_sysctl net.ipv4.udp_l3mdev_accept=0
+
+	#
+	# server tests
+	#
+	for a in ${NSA_IP} ${VRF_IP}
+	do
+		log_start
+		show_hint "Fails because ingress is in a VRF and global server is disabled"
+		run_cmd nettest -D -s &
+		sleep 1
+		run_cmd_nsb nettest -D -r ${a}
+		log_test_addr ${a} $? 1 "Global server"
+
+		log_start
+		run_cmd nettest -D -d ${VRF} -s -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd_nsb nettest -D -r ${a}
+		log_test_addr ${a} $? 0 "VRF server"
+
+		log_start
+		run_cmd nettest -D -d ${NSA_DEV} -s -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd_nsb nettest -D -r ${a}
+		log_test_addr ${a} $? 0 "Enslaved device server"
+
+		log_start
+		show_hint "Should fail 'Connection refused' since there is no server"
+		run_cmd_nsb nettest -D -r ${a}
+		log_test_addr ${a} $? 1 "No server"
+
+		log_start
+		show_hint "Should fail 'Connection refused' since global server is out of scope"
+		run_cmd nettest -D -s &
+		sleep 1
+		run_cmd nettest -D -d ${VRF} -r ${a}
+		log_test_addr ${a} $? 1 "Global server, VRF client, local connection"
+	done
+
+	a=${NSA_IP}
+	log_start
+	run_cmd nettest -s -D -d ${VRF} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -D -d ${VRF} -r ${a}
+	log_test_addr ${a} $? 0 "VRF server, VRF client, local conn"
+
+	log_start
+	run_cmd nettest -s -D -d ${VRF} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -D -d ${NSA_DEV} -r ${a}
+	log_test_addr ${a} $? 0 "VRF server, enslaved device client, local connection"
+
+	a=${NSA_IP}
+	log_start
+	run_cmd nettest -s -D -d ${NSA_DEV} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -D -d ${VRF} -r ${a}
+	log_test_addr ${a} $? 0 "Enslaved device server, VRF client, local conn"
+
+	log_start
+	run_cmd nettest -s -D -d ${NSA_DEV} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -D -d ${NSA_DEV} -r ${a}
+	log_test_addr ${a} $? 0 "Enslaved device server, device client, local conn"
+
+	# enable global server
+	log_subsection "Global server enabled"
+	set_sysctl net.ipv4.udp_l3mdev_accept=1
+
+	#
+	# server tests
+	#
+	for a in ${NSA_IP} ${VRF_IP}
+	do
+		log_start
+		run_cmd nettest -D -s -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd_nsb nettest -D -r ${a}
+		log_test_addr ${a} $? 0 "Global server"
+
+		log_start
+		run_cmd nettest -D -d ${VRF} -s -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd_nsb nettest -D -r ${a}
+		log_test_addr ${a} $? 0 "VRF server"
+
+		log_start
+		run_cmd nettest -D -d ${NSA_DEV} -s -2 ${NSA_DEV} &
+		sleep 1
+		run_cmd_nsb nettest -D -r ${a}
+		log_test_addr ${a} $? 0 "Enslaved device server"
+
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd_nsb nettest -D -r ${a}
+		log_test_addr ${a} $? 1 "No server"
+	done
+
+	#
+	# client tests
+	#
+	log_start
+	run_cmd_nsb nettest -D -s &
+	sleep 1
+	run_cmd nettest -d ${VRF} -D -r ${NSB_IP} -1 ${NSA_IP}
+	log_test $? 0 "VRF client"
+
+	log_start
+	run_cmd_nsb nettest -D -s &
+	sleep 1
+	run_cmd nettest -d ${NSA_DEV} -D -r ${NSB_IP} -1 ${NSA_IP}
+	log_test $? 0 "Enslaved device client"
+
+	# negative test - should fail
+	log_start
+	show_hint "Should fail 'Connection refused'"
+	run_cmd nettest -D -d ${VRF} -r ${NSB_IP}
+	log_test $? 1 "No server, VRF client"
+
+	log_start
+	show_hint "Should fail 'Connection refused'"
+	run_cmd nettest -D -d ${NSA_DEV} -r ${NSB_IP}
+	log_test $? 1 "No server, enslaved device client"
+
+	#
+	# local address tests
+	#
+	a=${NSA_IP}
+	log_start
+	run_cmd nettest -D -s -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -D -d ${VRF} -r ${a}
+	log_test_addr ${a} $? 0 "Global server, VRF client, local conn"
+
+	log_start
+	run_cmd nettest -s -D -d ${VRF} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -D -d ${VRF} -r ${a}
+	log_test_addr ${a} $? 0 "VRF server, VRF client, local conn"
+
+	log_start
+	run_cmd nettest -s -D -d ${VRF} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -D -d ${NSA_DEV} -r ${a}
+	log_test_addr ${a} $? 0 "VRF server, device client, local conn"
+
+	log_start
+	run_cmd nettest -s -D -d ${NSA_DEV} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -D -d ${VRF} -r ${a}
+	log_test_addr ${a} $? 0 "Enslaved device server, VRF client, local conn"
+
+	log_start
+	run_cmd nettest -s -D -d ${NSA_DEV} -2 ${NSA_DEV} &
+	sleep 1
+	run_cmd nettest -D -d ${NSA_DEV} -r ${a}
+	log_test_addr ${a} $? 0 "Enslaved device server, device client, local conn"
+
+	for a in ${VRF_IP} 127.0.0.1
+	do
+		log_start
+		run_cmd nettest -D -s -2 ${VRF} &
+		sleep 1
+		run_cmd nettest -D -d ${VRF} -r ${a}
+		log_test_addr ${a} $? 0 "Global server, VRF client, local conn"
+	done
+
+	for a in ${VRF_IP} 127.0.0.1
+	do
+		log_start
+		run_cmd nettest -s -D -d ${VRF} -2 ${VRF} &
+		sleep 1
+		run_cmd nettest -D -d ${VRF} -r ${a}
+		log_test_addr ${a} $? 0 "VRF server, VRF client, local conn"
+	done
+
+	# negative test - should fail
+	# verifies ECONNREFUSED
+	for a in ${NSA_IP} ${VRF_IP} 127.0.0.1
+	do
+		log_start
+		show_hint "Should fail 'Connection refused'"
+		run_cmd nettest -D -d ${VRF} -r ${a}
+		log_test_addr ${a} $? 1 "No server, VRF client, local conn"
+	done
+}
+
+ipv4_udp()
+{
+	which nettest >/dev/null
+	if [ $? -ne 0 ]; then
+		log_error "nettest not found; skipping tests"
+		return
+	fi
+
+	log_section "IPv4/UDP"
+	log_subsection "No VRF"
+
+	setup
+
+	# udp_l3mdev_accept should have no affect without VRF;
+	# run tests with it enabled and disabled to verify
+	log_subsection "udp_l3mdev_accept disabled"
+	set_sysctl net.ipv4.udp_l3mdev_accept=0
+	ipv4_udp_novrf
+	log_subsection "udp_l3mdev_accept enabled"
+	set_sysctl net.ipv4.udp_l3mdev_accept=1
+	ipv4_udp_novrf
+
+	log_subsection "With VRF"
+	setup "yes"
+	ipv4_udp_vrf
+}
+
+################################################################################
 # IPv6
 
 ipv6_ping_novrf()
@@ -1690,7 +2068,7 @@ EOF
 ################################################################################
 # main
 
-TESTS_IPV4="ipv4_ping ipv4_tcp"
+TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp"
 TESTS_IPV6="ipv6_ping ipv6_tcp"
 PAUSE_ON_FAIL=no
 PAUSE=no
@@ -1731,6 +2109,7 @@ do
 	case $t in
 	ipv4_ping|ping)  ipv4_ping;;
 	ipv4_tcp|tcp)    ipv4_tcp;;
+	ipv4_udp|udp)    ipv4_udp;;
 
 	ipv6_ping|ping6) ipv6_ping;;
 	ipv6_tcp|tcp6)   ipv6_tcp;;
-- 
2.11.0


^ permalink raw reply related

* [PATCH net-next 11/15] selftests: Add ipv4 runtime tests to fcnal-test
From: David Ahern @ 2019-08-01 18:56 UTC (permalink / raw)
  To: davem; +Cc: netdev, David Ahern
In-Reply-To: <20190801185648.27653-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Add runtime tests where passive (no traffic flowing) and active (with
traffic) sockets are expected to be reset on device deletes.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 tools/testing/selftests/net/fcnal-test.sh | 185 +++++++++++++++++++++++++++++-
 1 file changed, 184 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh
index 48e74d62e009..b8bdab733ecd 100755
--- a/tools/testing/selftests/net/fcnal-test.sh
+++ b/tools/testing/selftests/net/fcnal-test.sh
@@ -1509,6 +1509,188 @@ ipv4_addr_bind()
 }
 
 ################################################################################
+# IPv4 runtime tests
+
+ipv4_rt()
+{
+	local desc="$1"
+	local varg="$2"
+	local with_vrf="yes"
+	local a
+
+	#
+	# server tests
+	#
+	for a in ${NSA_IP} ${VRF_IP}
+	do
+		log_start
+		run_cmd nettest ${varg} -s &
+		sleep 1
+		run_cmd_nsb nettest ${varg} -r ${a} &
+		sleep 3
+		run_cmd ip link del ${VRF}
+		sleep 1
+		log_test_addr ${a} 0 0 "${desc}, global server"
+
+		setup ${with_vrf}
+	done
+
+	for a in ${NSA_IP} ${VRF_IP}
+	do
+		log_start
+		run_cmd nettest ${varg} -s -d ${VRF} &
+		sleep 1
+		run_cmd_nsb nettest ${varg} -r ${a} &
+		sleep 3
+		run_cmd ip link del ${VRF}
+		sleep 1
+		log_test_addr ${a} 0 0 "${desc}, VRF server"
+
+		setup ${with_vrf}
+	done
+
+	a=${NSA_IP}
+	log_start
+	run_cmd nettest ${varg} -s -d ${NSA_DEV} &
+	sleep 1
+	run_cmd_nsb nettest ${varg} -r ${a} &
+	sleep 3
+	run_cmd ip link del ${VRF}
+	sleep 1
+	log_test_addr ${a} 0 0 "${desc}, enslaved device server"
+
+	setup ${with_vrf}
+
+	#
+	# client test
+	#
+	log_start
+	run_cmd_nsb nettest ${varg} -s &
+	sleep 1
+	run_cmd nettest ${varg} -d ${VRF} -r ${NSB_IP} &
+	sleep 3
+	run_cmd ip link del ${VRF}
+	sleep 1
+	log_test_addr ${a} 0 0 "${desc}, VRF client"
+
+	setup ${with_vrf}
+
+	log_start
+	run_cmd_nsb nettest ${varg} -s &
+	sleep 1
+	run_cmd nettest ${varg} -d ${NSA_DEV} -r ${NSB_IP} &
+	sleep 3
+	run_cmd ip link del ${VRF}
+	sleep 1
+	log_test_addr ${a} 0 0 "${desc}, enslaved device client"
+
+	setup ${with_vrf}
+
+	#
+	# local address tests
+	#
+	for a in ${NSA_IP} ${VRF_IP}
+	do
+		log_start
+		run_cmd nettest ${varg} -s &
+		sleep 1
+		run_cmd nettest ${varg} -d ${VRF} -r ${a} &
+		sleep 3
+		run_cmd ip link del ${VRF}
+		sleep 1
+		log_test_addr ${a} 0 0 "${desc}, global server, VRF client, local"
+
+		setup ${with_vrf}
+	done
+
+	for a in ${NSA_IP} ${VRF_IP}
+	do
+		log_start
+		run_cmd nettest ${varg} -d ${VRF} -s &
+		sleep 1
+		run_cmd nettest ${varg} -d ${VRF} -r ${a} &
+		sleep 3
+		run_cmd ip link del ${VRF}
+		sleep 1
+		log_test_addr ${a} 0 0 "${desc}, VRF server and client, local"
+
+		setup ${with_vrf}
+	done
+
+	a=${NSA_IP}
+	log_start
+	run_cmd nettest ${varg} -s &
+	sleep 1
+	run_cmd nettest ${varg} -d ${NSA_DEV} -r ${a} &
+	sleep 3
+	run_cmd ip link del ${VRF}
+	sleep 1
+	log_test_addr ${a} 0 0 "${desc}, global server, enslaved device client, local"
+
+	setup ${with_vrf}
+
+	log_start
+	run_cmd nettest ${varg} -d ${VRF} -s &
+	sleep 1
+	run_cmd nettest ${varg} -d ${NSA_DEV} -r ${a} &
+	sleep 3
+	run_cmd ip link del ${VRF}
+	sleep 1
+	log_test_addr ${a} 0 0 "${desc}, VRF server, enslaved device client, local"
+
+	setup ${with_vrf}
+
+	log_start
+	run_cmd nettest ${varg} -d ${NSA_DEV} -s &
+	sleep 1
+	run_cmd nettest ${varg} -d ${NSA_DEV} -r ${a} &
+	sleep 3
+	run_cmd ip link del ${VRF}
+	sleep 1
+	log_test_addr ${a} 0 0 "${desc}, enslaved device server and client, local"
+}
+
+ipv4_ping_rt()
+{
+	local with_vrf="yes"
+	local a
+
+	for a in ${NSA_IP} ${VRF_IP}
+	do
+		log_start
+		run_cmd_nsb ping -f ${a} &
+		sleep 3
+		run_cmd ip link del ${VRF}
+		sleep 1
+		log_test_addr ${a} 0 0 "Device delete with active traffic - ping in"
+
+		setup ${with_vrf}
+	done
+
+	a=${NSB_IP}
+	log_start
+	run_cmd ping -f -I ${VRF} ${a} &
+	sleep 3
+	run_cmd ip link del ${VRF}
+	sleep 1
+	log_test_addr ${a} 0 0 "Device delete with active traffic - ping out"
+}
+
+ipv4_runtime()
+{
+	log_section "Run time tests - ipv4"
+
+	setup "yes"
+	ipv4_ping_rt
+
+	setup "yes"
+	ipv4_rt "TCP active socket"  "-n -1"
+
+	setup "yes"
+	ipv4_rt "TCP passive socket" "-i"
+}
+
+################################################################################
 # IPv6
 
 ipv6_ping_novrf()
@@ -2772,7 +2954,7 @@ EOF
 ################################################################################
 # main
 
-TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind"
+TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind ipv4_runtime"
 TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_addr_bind"
 PAUSE_ON_FAIL=no
 PAUSE=no
@@ -2815,6 +2997,7 @@ do
 	ipv4_tcp|tcp)    ipv4_tcp;;
 	ipv4_udp|udp)    ipv4_udp;;
 	ipv4_bind|bind)  ipv4_addr_bind;;
+	ipv4_runtime)    ipv4_runtime;;
 
 	ipv6_ping|ping6) ipv6_ping;;
 	ipv6_tcp|tcp6)   ipv6_tcp;;
-- 
2.11.0


^ permalink raw reply related

* [PATCH net-next 13/15] selftests: Add ipv4 netfilter tests to fcnal-test
From: David Ahern @ 2019-08-01 18:56 UTC (permalink / raw)
  To: davem; +Cc: netdev, David Ahern
In-Reply-To: <20190801185648.27653-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Add netfilter tests to send tcp reset or icmp unreachable for a port.
Initial tests are VRF only.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 tools/testing/selftests/net/fcnal-test.sh | 69 ++++++++++++++++++++++++++++++-
 1 file changed, 68 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh
index dcfe0b13dfe9..6f56c91e2d66 100755
--- a/tools/testing/selftests/net/fcnal-test.sh
+++ b/tools/testing/selftests/net/fcnal-test.sh
@@ -3120,6 +3120,72 @@ ipv6_runtime()
 }
 
 ################################################################################
+# netfilter blocking connections
+
+netfilter_tcp_reset()
+{
+	local a
+
+	for a in ${NSA_IP} ${VRF_IP}
+	do
+		log_start
+		run_cmd nettest -s &
+		sleep 1
+		run_cmd_nsb nettest -r ${a}
+		log_test_addr ${a} $? 1 "Global server, reject with TCP-reset on Rx"
+	done
+}
+
+netfilter_icmp()
+{
+	local stype="$1"
+	local arg
+	local a
+
+	[ "${stype}" = "UDP" ] && arg="-D"
+
+	for a in ${NSA_IP} ${VRF_IP}
+	do
+		log_start
+		run_cmd nettest ${arg} -s &
+		sleep 1
+		run_cmd_nsb nettest ${arg} -r ${a}
+		log_test_addr ${a} $? 1 "Global ${stype} server, Rx reject icmp-port-unreach"
+	done
+}
+
+ipv4_netfilter()
+{
+	which nettest >/dev/null
+	if [ $? -ne 0 ]; then
+		log_error "nettest not found; skipping tests"
+		return
+	fi
+
+	log_section "IPv4 Netfilter"
+	log_subsection "TCP reset"
+
+	setup "yes"
+	run_cmd iptables -A INPUT -p tcp --dport 12345 -j REJECT --reject-with tcp-reset
+
+	netfilter_tcp_reset
+
+	log_start
+	log_subsection "ICMP unreachable"
+
+	log_start
+	run_cmd iptables -F
+	run_cmd iptables -A INPUT -p tcp --dport 12345 -j REJECT --reject-with icmp-port-unreachable
+	run_cmd iptables -A INPUT -p udp --dport 12345 -j REJECT --reject-with icmp-port-unreachable
+
+	netfilter_icmp "TCP"
+	netfilter_icmp "UDP"
+
+	log_start
+	iptables -F
+}
+
+################################################################################
 # usage
 
 usage()
@@ -3139,7 +3205,7 @@ EOF
 ################################################################################
 # main
 
-TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind ipv4_runtime"
+TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind ipv4_runtime ipv4_netfilter"
 TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_addr_bind ipv6_runtime"
 PAUSE_ON_FAIL=no
 PAUSE=no
@@ -3183,6 +3249,7 @@ do
 	ipv4_udp|udp)    ipv4_udp;;
 	ipv4_bind|bind)  ipv4_addr_bind;;
 	ipv4_runtime)    ipv4_runtime;;
+	ipv4_netfilter)  ipv4_netfilter;;
 
 	ipv6_ping|ping6) ipv6_ping;;
 	ipv6_tcp|tcp6)   ipv6_tcp;;
-- 
2.11.0


^ permalink raw reply related


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