net/mlx5e: Calculate linear RX frag size considering XSK
authorMaxim Mikityanskiy <maximmi@mellanox.com>
Wed, 26 Jun 2019 14:35:30 +0000 (17:35 +0300)
committerDaniel Borkmann <daniel@iogearbox.net>
Thu, 27 Jun 2019 20:53:27 +0000 (22:53 +0200)
Additional conditions introduced:

- XSK implies XDP.
- Headroom includes the XSK headroom if it exists.
- No space is reserved for struct shared_skb_info in XSK mode.
- Fragment size smaller than the XSK chunk size is not allowed.

A new auxiliary function mlx5e_get_linear_rq_headroom with the support
for XSK is introduced. Use this function in the implementation of
mlx5e_get_rq_headroom. Change headroom to u32 to match the headroom
field in struct xdp_umem.

Signed-off-by: Maxim Mikityanskiy <maximmi@mellanox.com>
Signed-off-by: Tariq Toukan <tariqt@mellanox.com>
Acked-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
drivers/net/ethernet/mellanox/mlx5/core/en/params.c
drivers/net/ethernet/mellanox/mlx5/core/en/params.h
drivers/net/ethernet/mellanox/mlx5/core/en_main.c

index d3744bf..50a458d 100644 (file)
@@ -3,33 +3,62 @@
 
 #include "en/params.h"
 
-u32 mlx5e_rx_get_linear_frag_sz(struct mlx5e_params *params)
+static inline bool mlx5e_rx_is_xdp(struct mlx5e_params *params,
+                                  struct mlx5e_xsk_param *xsk)
 {
-       u16 hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu);
-       u16 linear_rq_headroom = params->xdp_prog ?
-               XDP_PACKET_HEADROOM : MLX5_RX_HEADROOM;
-       u32 frag_sz;
+       return params->xdp_prog || xsk;
+}
+
+static inline u16 mlx5e_get_linear_rq_headroom(struct mlx5e_params *params,
+                                              struct mlx5e_xsk_param *xsk)
+{
+       u16 headroom = NET_IP_ALIGN;
+
+       if (mlx5e_rx_is_xdp(params, xsk)) {
+               headroom += XDP_PACKET_HEADROOM;
+               if (xsk)
+                       headroom += xsk->headroom;
+       } else {
+               headroom += MLX5_RX_HEADROOM;
+       }
+
+       return headroom;
+}
+
+u32 mlx5e_rx_get_linear_frag_sz(struct mlx5e_params *params,
+                               struct mlx5e_xsk_param *xsk)
+{
+       u32 hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu);
+       u16 linear_rq_headroom = mlx5e_get_linear_rq_headroom(params, xsk);
+       u32 frag_sz = linear_rq_headroom + hw_mtu;
 
-       linear_rq_headroom += NET_IP_ALIGN;
+       /* AF_XDP doesn't build SKBs in place. */
+       if (!xsk)
+               frag_sz = MLX5_SKB_FRAG_SZ(frag_sz);
 
-       frag_sz = MLX5_SKB_FRAG_SZ(linear_rq_headroom + hw_mtu);
+       /* XDP in mlx5e doesn't support multiple packets per page. */
+       if (mlx5e_rx_is_xdp(params, xsk))
+               frag_sz = max_t(u32, frag_sz, PAGE_SIZE);
 
-       if (params->xdp_prog && frag_sz < PAGE_SIZE)
-               frag_sz = PAGE_SIZE;
+       /* Even if we can go with a smaller fragment size, we must not put
+        * multiple packets into a single frame.
+        */
+       if (xsk)
+               frag_sz = max_t(u32, frag_sz, xsk->chunk_size);
 
        return frag_sz;
 }
 
 u8 mlx5e_mpwqe_log_pkts_per_wqe(struct mlx5e_params *params)
 {
-       u32 linear_frag_sz = mlx5e_rx_get_linear_frag_sz(params);
+       u32 linear_frag_sz = mlx5e_rx_get_linear_frag_sz(params, NULL);
 
        return MLX5_MPWRQ_LOG_WQE_SZ - order_base_2(linear_frag_sz);
 }
 
 bool mlx5e_rx_is_linear_skb(struct mlx5e_params *params)
 {
-       u32 frag_sz = mlx5e_rx_get_linear_frag_sz(params);
+       u32 frag_sz = mlx5e_rx_get_linear_frag_sz(params, NULL);
 
        return !params->lro_en && frag_sz <= PAGE_SIZE;
 }
@@ -39,7 +68,7 @@ bool mlx5e_rx_is_linear_skb(struct mlx5e_params *params)
 bool mlx5e_rx_mpwqe_is_linear_skb(struct mlx5_core_dev *mdev,
                                  struct mlx5e_params *params)
 {
-       u32 frag_sz = mlx5e_rx_get_linear_frag_sz(params);
+       u32 frag_sz = mlx5e_rx_get_linear_frag_sz(params, NULL);
        s8 signed_log_num_strides_param;
        u8 log_num_strides;
 
@@ -75,7 +104,7 @@ u8 mlx5e_mpwqe_get_log_stride_size(struct mlx5_core_dev *mdev,
                                   struct mlx5e_params *params)
 {
        if (mlx5e_rx_mpwqe_is_linear_skb(mdev, params))
-               return order_base_2(mlx5e_rx_get_linear_frag_sz(params));
+               return order_base_2(mlx5e_rx_get_linear_frag_sz(params, NULL));
 
        return MLX5_MPWRQ_DEF_LOG_STRIDE_SZ(mdev);
 }
@@ -90,15 +119,9 @@ u8 mlx5e_mpwqe_get_log_num_strides(struct mlx5_core_dev *mdev,
 u16 mlx5e_get_rq_headroom(struct mlx5_core_dev *mdev,
                          struct mlx5e_params *params)
 {
-       u16 linear_rq_headroom = params->xdp_prog ?
-               XDP_PACKET_HEADROOM : MLX5_RX_HEADROOM;
-       bool is_linear_skb;
-
-       linear_rq_headroom += NET_IP_ALIGN;
-
-       is_linear_skb = (params->rq_wq_type == MLX5_WQ_TYPE_CYCLIC) ?
+       bool is_linear_skb = (params->rq_wq_type == MLX5_WQ_TYPE_CYCLIC) ?
                mlx5e_rx_is_linear_skb(params) :
                mlx5e_rx_mpwqe_is_linear_skb(mdev, params);
 
-       return is_linear_skb ? linear_rq_headroom : 0;
+       return is_linear_skb ? mlx5e_get_linear_rq_headroom(params, NULL) : 0;
 }
index b106a02..ed420f3 100644 (file)
@@ -6,7 +6,13 @@
 
 #include "en.h"
 
-u32 mlx5e_rx_get_linear_frag_sz(struct mlx5e_params *params);
+struct mlx5e_xsk_param {
+       u16 headroom;
+       u16 chunk_size;
+};
+
+u32 mlx5e_rx_get_linear_frag_sz(struct mlx5e_params *params,
+                               struct mlx5e_xsk_param *xsk);
 u8 mlx5e_mpwqe_log_pkts_per_wqe(struct mlx5e_params *params);
 bool mlx5e_rx_is_linear_skb(struct mlx5e_params *params);
 bool mlx5e_rx_mpwqe_is_linear_skb(struct mlx5_core_dev *mdev,
index 1b427d7..837a973 100644 (file)
@@ -1954,7 +1954,7 @@ static void mlx5e_build_rq_frags_info(struct mlx5_core_dev *mdev,
        if (mlx5e_rx_is_linear_skb(params)) {
                int frag_stride;
 
-               frag_stride = mlx5e_rx_get_linear_frag_sz(params);
+               frag_stride = mlx5e_rx_get_linear_frag_sz(params, NULL);
                frag_stride = roundup_pow_of_two(frag_stride);
 
                info->arr[0].frag_size = byte_count;