Merge branch 'ct-offload' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed...
authorDavid S. Miller <davem@davemloft.net>
Thu, 12 Mar 2020 19:34:23 +0000 (12:34 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 12 Mar 2020 19:34:23 +0000 (12:34 -0700)
14 files changed:
1  2 
drivers/infiniband/hw/mlx5/main.c
drivers/net/ethernet/mellanox/mlx5/core/Makefile
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.h
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
include/net/pkt_cls.h
net/core/dev.c
net/sched/cls_api.c

Simple merge
@@@ -1272,8 -1372,11 +1372,10 @@@ static void mlx5e_tc_del_fdb_flow(struc
  {
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
        struct mlx5_esw_flow_attr *attr = flow->esw_attr;
 -      struct mlx5_esw_flow_attr slow_attr;
        int out_index;
  
+       mlx5e_put_flow_tunnel_id(flow);
        if (flow_flag_test(flow, NOT_READY)) {
                remove_unready_flow(flow);
                kvfree(attr->parse_attr);
@@@ -3571,17 -3750,28 +3815,17 @@@ static int parse_tc_fdb_actions(struct 
                        attr->split_count = attr->out_count;
                        break;
                case FLOW_ACTION_TUNNEL_DECAP:
-                       action |= MLX5_FLOW_CONTEXT_ACTION_DECAP;
+                       decap = true;
                        break;
 -              case FLOW_ACTION_GOTO: {
 -                      u32 dest_chain = act->chain_index;
 -                      u32 max_chain = mlx5_esw_chains_get_chain_range(esw);
 +              case FLOW_ACTION_GOTO:
 +                      err = mlx5_validate_goto_chain(esw, flow, act, action,
 +                                                     extack);
 +                      if (err)
 +                              return err;
  
 -                      if (ft_flow) {
 -                              NL_SET_ERR_MSG_MOD(extack, "Goto action is not supported");
 -                              return -EOPNOTSUPP;
 -                      }
 -                      if (dest_chain <= attr->chain) {
 -                              NL_SET_ERR_MSG(extack, "Goto earlier chain isn't supported");
 -                              return -EOPNOTSUPP;
 -                      }
 -                      if (dest_chain > max_chain) {
 -                              NL_SET_ERR_MSG(extack, "Requested destination chain is out of supported range");
 -                              return -EOPNOTSUPP;
 -                      }
                        action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
 -                      attr->dest_chain = dest_chain;
 +                      attr->dest_chain = act->chain_index;
                        break;
 -                      }
                default:
                        NL_SET_ERR_MSG_MOD(extack, "The offload action is not supported");
                        return -EOPNOTSUPP;
                return -EOPNOTSUPP;
  
        if (attr->dest_chain) {
+               if (decap) {
+                       /* It can be supported if we'll create a mapping for
+                        * the tunnel device only (without tunnel), and set
+                        * this tunnel id with this decap flow.
+                        *
+                        * On restore (miss), we'll just set this saved tunnel
+                        * device.
+                        */
+                       NL_SET_ERR_MSG(extack,
+                                      "Decap with goto isn't supported");
+                       netdev_warn(priv->netdev,
+                                   "Decap with goto isn't supported");
+                       return -EOPNOTSUPP;
+               }
                if (attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
 -                      NL_SET_ERR_MSG(extack, "Mirroring goto chain rules isn't supported");
 +                      NL_SET_ERR_MSG_MOD(extack,
 +                                         "Mirroring goto chain rules isn't supported");
                        return -EOPNOTSUPP;
                }
                attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
@@@ -633,9 -627,11 +637,14 @@@ voi
  esw_vport_destroy_offloads_acl_tables(struct mlx5_eswitch *esw,
                                      struct mlx5_vport *vport);
  
 +int mlx5_esw_vport_tbl_get(struct mlx5_eswitch *esw);
 +void mlx5_esw_vport_tbl_put(struct mlx5_eswitch *esw);
 +
+ struct mlx5_flow_handle *
+ esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag);
+ u32
+ esw_get_max_restore_tag(struct mlx5_eswitch *esw);
  #else  /* CONFIG_MLX5_ESWITCH */
  /* eswitch API stubs */
  static inline int  mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; }
        return flow_rule;
  }
  
++
 +static int mlx5_eswitch_inline_mode_get(const struct mlx5_eswitch *esw, u8 *mode)
 +{
 +      u8 prev_mlx5_mode, mlx5_mode = MLX5_INLINE_MODE_L2;
 +      struct mlx5_core_dev *dev = esw->dev;
 +      int vport;
 +
 +      if (!MLX5_CAP_GEN(dev, vport_group_manager))
 +              return -EOPNOTSUPP;
 +
 +      if (esw->mode == MLX5_ESWITCH_NONE)
 +              return -EOPNOTSUPP;
 +
 +      switch (MLX5_CAP_ETH(dev, wqe_inline_mode)) {
 +      case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
 +              mlx5_mode = MLX5_INLINE_MODE_NONE;
 +              goto out;
 +      case MLX5_CAP_INLINE_MODE_L2:
 +              mlx5_mode = MLX5_INLINE_MODE_L2;
 +              goto out;
 +      case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT:
 +              goto query_vports;
 +      }
 +
 +query_vports:
 +      mlx5_query_nic_vport_min_inline(dev, esw->first_host_vport, &prev_mlx5_mode);
 +      mlx5_esw_for_each_host_func_vport(esw, vport, esw->esw_funcs.num_vfs) {
 +              mlx5_query_nic_vport_min_inline(dev, vport, &mlx5_mode);
 +              if (prev_mlx5_mode != mlx5_mode)
 +                      return -EINVAL;
 +              prev_mlx5_mode = mlx5_mode;
 +      }
 +
 +out:
 +      *mode = mlx5_mode;
 +      return 0;
++}       
++
+ static void esw_destroy_restore_table(struct mlx5_eswitch *esw)
+ {
+       struct mlx5_esw_offload *offloads = &esw->offloads;
+       mlx5_modify_header_dealloc(esw->dev, offloads->restore_copy_hdr_id);
+       mlx5_destroy_flow_group(offloads->restore_group);
+       mlx5_destroy_flow_table(offloads->ft_offloads_restore);
+ }
+ static int esw_create_restore_table(struct mlx5_eswitch *esw)
+ {
+       u8 modact[MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto)] = {};
+       int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
+       struct mlx5_flow_table_attr ft_attr = {};
+       struct mlx5_core_dev *dev = esw->dev;
+       struct mlx5_flow_namespace *ns;
+       struct mlx5_modify_hdr *mod_hdr;
+       void *match_criteria, *misc;
+       struct mlx5_flow_table *ft;
+       struct mlx5_flow_group *g;
+       u32 *flow_group_in;
+       int err = 0;
+       ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_OFFLOADS);
+       if (!ns) {
+               esw_warn(esw->dev, "Failed to get offloads flow namespace\n");
+               return -EOPNOTSUPP;
+       }
+       flow_group_in = kvzalloc(inlen, GFP_KERNEL);
+       if (!flow_group_in) {
+               err = -ENOMEM;
+               goto out_free;
+       }
+       ft_attr.max_fte = 1 << ESW_CHAIN_TAG_METADATA_BITS;
+       ft = mlx5_create_flow_table(ns, &ft_attr);
+       if (IS_ERR(ft)) {
+               err = PTR_ERR(ft);
+               esw_warn(esw->dev, "Failed to create restore table, err %d\n",
+                        err);
+               goto out_free;
+       }
+       memset(flow_group_in, 0, inlen);
+       match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in,
+                                     match_criteria);
+       misc = MLX5_ADDR_OF(fte_match_param, match_criteria,
+                           misc_parameters_2);
+       MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
+                ESW_CHAIN_TAG_METADATA_MASK);
+       MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
+       MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
+                ft_attr.max_fte - 1);
+       MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
+                MLX5_MATCH_MISC_PARAMETERS_2);
+       g = mlx5_create_flow_group(ft, flow_group_in);
+       if (IS_ERR(g)) {
+               err = PTR_ERR(g);
+               esw_warn(dev, "Failed to create restore flow group, err: %d\n",
+                        err);
+               goto err_group;
+       }
+       MLX5_SET(copy_action_in, modact, action_type, MLX5_ACTION_TYPE_COPY);
+       MLX5_SET(copy_action_in, modact, src_field,
+                MLX5_ACTION_IN_FIELD_METADATA_REG_C_1);
+       MLX5_SET(copy_action_in, modact, dst_field,
+                MLX5_ACTION_IN_FIELD_METADATA_REG_B);
+       mod_hdr = mlx5_modify_header_alloc(esw->dev,
+                                          MLX5_FLOW_NAMESPACE_KERNEL, 1,
+                                          modact);
+       if (IS_ERR(mod_hdr)) {
+               esw_warn(dev, "Failed to create restore mod header, err: %d\n",
+                        err);
+               err = PTR_ERR(mod_hdr);
+               goto err_mod_hdr;
+       }
+       esw->offloads.ft_offloads_restore = ft;
+       esw->offloads.restore_group = g;
+       esw->offloads.restore_copy_hdr_id = mod_hdr;
+       return 0;
+ err_mod_hdr:
+       mlx5_destroy_flow_group(g);
+ err_group:
+       mlx5_destroy_flow_table(ft);
+ out_free:
+       kvfree(flow_group_in);
+       return err;
  }
  
  static int esw_offloads_start(struct mlx5_eswitch *esw,
@@@ -2175,10 -2104,10 +2341,11 @@@ create_offloads_err
  
  static void esw_offloads_steering_cleanup(struct mlx5_eswitch *esw)
  {
 +      mutex_destroy(&esw->fdb_table.offloads.vports.lock);
        esw_destroy_vport_rx_group(esw);
-       esw_destroy_offloads_table(esw);
        esw_destroy_offloads_fdb_tables(esw);
+       esw_destroy_restore_table(esw);
+       esw_destroy_offloads_table(esw);
        esw_destroy_uplink_offloads_acl_tables(esw);
  }
  
  #define ANCHOR_NUM_PRIOS 1
  #define ANCHOR_MIN_LEVEL (BY_PASS_MIN_LEVEL + 1)
  
 -#define OFFLOADS_MAX_FT 1
 +#define OFFLOADS_MAX_FT 2
- #define OFFLOADS_NUM_PRIOS 1
- #define OFFLOADS_MIN_LEVEL (ANCHOR_MIN_LEVEL + 1)
+ #define OFFLOADS_NUM_PRIOS 2
+ #define OFFLOADS_MIN_LEVEL (ANCHOR_MIN_LEVEL + OFFLOADS_NUM_PRIOS)
  
  #define LAG_PRIO_NUM_LEVELS 1
  #define LAG_NUM_PRIOS 1
Simple merge
diff --cc net/core/dev.c
Simple merge
Simple merge