Skip to content

Commit

Permalink
Merge tag 'mlx5-updates-2018-02-28-1' of git://git.kernel.org/pub/scm…
Browse files Browse the repository at this point in the history
…/linux/kernel/git/mellanox/linux into k.o/wip/dl-for-next

mlx5-updates-2018-02-28-1 (IPSec-1)

This series consists of some fixes and refactors for the mlx5 drivers,
especially around the FPGA and flow steering. Most of them are trivial
fixes and are the foundation of allowing IPSec acceleration from user-space.

We use flow steering abstraction in order to accelerate IPSec packets.
When a user creates a steering rule, [s]he states that we'll carry an
encrypt/decrypt flow action (using a specific configuration) for every
packet which conforms to a certain match. Since currently offloading these
packets is done via FPGA, we'll add another set of flow steering ops.
These ops will execute the required FPGA commands and then call the
standard steering ops.

In order to achieve this, we need that the commands will get all the
required information. Therefore, we pass the fte object and embed the
flow_action struct inside the fte. In addition, we add the shim layer
that will later be used for alternating between the standard and the
FPGA steering commands.

Some fixes, like " net/mlx5e: Wait for FPGA command responses with a timeout"
are very relevant for user-space applications, as these applications could
be killed, but we still want to wait for the FPGA and update the kernel's
database.

Regards,
Aviad and Matan

Signed-off-by: Doug Ledford <dledford@redhat.com>
  • Loading branch information
Doug Ledford authored and Jason Gunthorpe committed Mar 7, 2018
2 parents befd8d9 + e810bf5 commit 1abb791
Show file tree
Hide file tree
Showing 16 changed files with 494 additions and 184 deletions.
30 changes: 12 additions & 18 deletions drivers/infiniband/hw/mlx5/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
#include "mlx5_ib.h"
#include "ib_rep.h"
#include "cmd.h"
#include <linux/mlx5/fs_helpers.h>

#define DRIVER_NAME "mlx5_ib"
#define DRIVER_VERSION "5.0-0"
Expand Down Expand Up @@ -2312,11 +2313,9 @@ static void set_tos(void *outer_c, void *outer_v, u8 mask, u8 val)
offsetof(typeof(filter), field) -\
sizeof(filter.field))

#define IPV4_VERSION 4
#define IPV6_VERSION 6
static int parse_flow_attr(struct mlx5_core_dev *mdev, u32 *match_c,
u32 *match_v, const union ib_flow_spec *ib_spec,
u32 *tag_id, bool *is_drop)
struct mlx5_flow_act *action)
{
void *misc_params_c = MLX5_ADDR_OF(fte_match_param, match_c,
misc_parameters);
Expand Down Expand Up @@ -2399,7 +2398,7 @@ static int parse_flow_attr(struct mlx5_core_dev *mdev, u32 *match_c,
MLX5_SET(fte_match_set_lyr_2_4, headers_c,
ip_version, 0xf);
MLX5_SET(fte_match_set_lyr_2_4, headers_v,
ip_version, IPV4_VERSION);
ip_version, MLX5_FS_IPV4_VERSION);
} else {
MLX5_SET(fte_match_set_lyr_2_4, headers_c,
ethertype, 0xffff);
Expand Down Expand Up @@ -2438,7 +2437,7 @@ static int parse_flow_attr(struct mlx5_core_dev *mdev, u32 *match_c,
MLX5_SET(fte_match_set_lyr_2_4, headers_c,
ip_version, 0xf);
MLX5_SET(fte_match_set_lyr_2_4, headers_v,
ip_version, IPV6_VERSION);
ip_version, MLX5_FS_IPV6_VERSION);
} else {
MLX5_SET(fte_match_set_lyr_2_4, headers_c,
ethertype, 0xffff);
Expand Down Expand Up @@ -2534,13 +2533,14 @@ static int parse_flow_attr(struct mlx5_core_dev *mdev, u32 *match_c,
if (ib_spec->flow_tag.tag_id >= BIT(24))
return -EINVAL;

*tag_id = ib_spec->flow_tag.tag_id;
action->flow_tag = ib_spec->flow_tag.tag_id;
action->has_flow_tag = true;
break;
case IB_FLOW_SPEC_ACTION_DROP:
if (FIELDS_NOT_SUPPORTED(ib_spec->drop,
LAST_DROP_FIELD))
return -EOPNOTSUPP;
*is_drop = true;
action->action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
break;
default:
return -EINVAL;
Expand Down Expand Up @@ -2793,13 +2793,11 @@ static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev,
{
struct mlx5_flow_table *ft = ft_prio->flow_table;
struct mlx5_ib_flow_handler *handler;
struct mlx5_flow_act flow_act = {0};
struct mlx5_flow_act flow_act = {.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG};
struct mlx5_flow_spec *spec;
struct mlx5_flow_destination *rule_dst = dst;
const void *ib_flow = (const void *)flow_attr + sizeof(*flow_attr);
unsigned int spec_index;
u32 flow_tag = MLX5_FS_DEFAULT_FLOW_TAG;
bool is_drop = false;
int err = 0;
int dest_num = 1;

Expand All @@ -2818,7 +2816,7 @@ static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev,
for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) {
err = parse_flow_attr(dev->mdev, spec->match_criteria,
spec->match_value,
ib_flow, &flow_tag, &is_drop);
ib_flow, &flow_act);
if (err < 0)
goto free;

Expand All @@ -2841,24 +2839,22 @@ static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev,
}

spec->match_criteria_enable = get_match_criteria_enable(spec->match_criteria);
if (is_drop) {
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DROP) {
rule_dst = NULL;
dest_num = 0;
} else {
flow_act.action = dst ? MLX5_FLOW_CONTEXT_ACTION_FWD_DEST :
MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
}

if (flow_tag != MLX5_FS_DEFAULT_FLOW_TAG &&
if (flow_act.has_flow_tag &&
(flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT)) {
mlx5_ib_warn(dev, "Flow tag %u and attribute type %x isn't allowed in leftovers\n",
flow_tag, flow_attr->type);
flow_act.flow_tag, flow_attr->type);
err = -EINVAL;
goto free;
}
flow_act.flow_tag = flow_tag;
handler->rule = mlx5_add_flow_rules(ft, spec,
&flow_act,
rule_dst, dest_num);
Expand Down Expand Up @@ -4585,8 +4581,6 @@ int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
goto err_free_port;

if (!mlx5_core_mp_enabled(mdev)) {
int i;

for (i = 1; i <= dev->num_ports; i++) {
err = get_port_caps(dev, i);
if (err)
Expand Down
3 changes: 0 additions & 3 deletions drivers/infiniband/hw/mlx5/qp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2153,7 +2153,6 @@ static struct ib_qp *mlx5_ib_create_dct(struct ib_pd *pd,
struct ib_qp_init_attr *attr,
struct mlx5_ib_create_qp *ucmd)
{
struct mlx5_ib_dev *dev;
struct mlx5_ib_qp *qp;
int err = 0;
u32 uidx = MLX5_IB_DEFAULT_UIDX;
Expand All @@ -2162,8 +2161,6 @@ static struct ib_qp *mlx5_ib_create_dct(struct ib_pd *pd,
if (!attr->srq || !attr->recv_cq)
return ERR_PTR(-EINVAL);

dev = to_mdev(pd->device);

err = get_qp_user_index(to_mucontext(pd->uobject->context),
ucmd, sizeof(*ucmd), &uidx);
if (err)
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/mellanox/mlx5/core/accel/ipsec.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@
#ifndef __MLX5_ACCEL_IPSEC_H__
#define __MLX5_ACCEL_IPSEC_H__

#ifdef CONFIG_MLX5_ACCEL

#include <linux/mlx5/driver.h>

#ifdef CONFIG_MLX5_ACCEL

enum {
MLX5_ACCEL_IPSEC_DEVICE = BIT(1),
MLX5_ACCEL_IPSEC_IPV6 = BIT(2),
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@ const char *parse_fs_dst(struct trace_seq *p,
case MLX5_FLOW_DESTINATION_TYPE_COUNTER:
trace_seq_printf(p, "counter_id=%u\n", counter_id);
break;
case MLX5_FLOW_DESTINATION_TYPE_PORT:
trace_seq_printf(p, "port\n");
break;
}

trace_seq_putc(p, 0);
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,9 @@ TRACE_EVENT(mlx5_fs_set_fte,
fs_get_obj(__entry->fg, fte->node.parent);
__entry->group_index = __entry->fg->id;
__entry->index = fte->index;
__entry->action = fte->action;
__entry->action = fte->action.action;
__entry->mask_enable = __entry->fg->mask.match_criteria_enable;
__entry->flow_tag = fte->flow_tag;
__entry->flow_tag = fte->action.flow_tag;
memcpy(__entry->mask_outer,
MLX5_ADDR_OF(fte_match_param,
&__entry->fg->mask.match_criteria,
Expand Down
17 changes: 6 additions & 11 deletions drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,16 @@ static int mlx5e_ipsec_sadb_rx_add(struct mlx5e_ipsec_sa_entry *sa_entry)
unsigned long flags;
int ret;

spin_lock_irqsave(&ipsec->sadb_rx_lock, flags);
ret = ida_simple_get(&ipsec->halloc, 1, 0, GFP_KERNEL);
if (ret < 0)
goto out;
return ret;

spin_lock_irqsave(&ipsec->sadb_rx_lock, flags);
sa_entry->handle = ret;
hash_add_rcu(ipsec->sadb_rx, &sa_entry->hlist, sa_entry->handle);
ret = 0;

out:
spin_unlock_irqrestore(&ipsec->sadb_rx_lock, flags);
return ret;

return 0;
}

static void mlx5e_ipsec_sadb_rx_del(struct mlx5e_ipsec_sa_entry *sa_entry)
Expand All @@ -101,13 +99,10 @@ static void mlx5e_ipsec_sadb_rx_del(struct mlx5e_ipsec_sa_entry *sa_entry)
static void mlx5e_ipsec_sadb_rx_free(struct mlx5e_ipsec_sa_entry *sa_entry)
{
struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
unsigned long flags;

/* Wait for the hash_del_rcu call in sadb_rx_del to affect data path */
synchronize_rcu();
spin_lock_irqsave(&ipsec->sadb_rx_lock, flags);
/* xfrm already doing sync rcu between del and free callbacks */

ida_simple_remove(&ipsec->halloc, sa_entry->handle);
spin_unlock_irqrestore(&ipsec->sadb_rx_lock, flags);
}

static enum mlx5_accel_ipsec_enc_mode mlx5e_ipsec_enc_mode(struct xfrm_state *x)
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
struct mlx5_flow_destination dest[2] = {};
struct mlx5_flow_act flow_act = {
.action = attr->action,
.has_flow_tag = true,
.flow_tag = attr->flow_tag,
.encap_id = 0,
};
Expand Down
9 changes: 6 additions & 3 deletions drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "fpga/core.h"

#define SBU_QP_QUEUE_SIZE 8
#define MLX5_FPGA_IPSEC_CMD_TIMEOUT_MSEC (60 * 1000)

enum mlx5_ipsec_response_syndrome {
MLX5_IPSEC_RESPONSE_SUCCESS = 0,
Expand Down Expand Up @@ -217,12 +218,14 @@ void *mlx5_fpga_ipsec_sa_cmd_exec(struct mlx5_core_dev *mdev,
int mlx5_fpga_ipsec_sa_cmd_wait(void *ctx)
{
struct mlx5_ipsec_command_context *context = ctx;
unsigned long timeout =
msecs_to_jiffies(MLX5_FPGA_IPSEC_CMD_TIMEOUT_MSEC);
int res;

res = wait_for_completion_killable(&context->complete);
if (res) {
res = wait_for_completion_timeout(&context->complete, timeout);
if (!res) {
mlx5_fpga_warn(context->dev, "Failure waiting for IPSec command response\n");
return -EINTR;
return -ETIMEDOUT;
}

if (context->status == MLX5_FPGA_IPSEC_SACMD_COMPLETE)
Expand Down
Loading

0 comments on commit 1abb791

Please sign in to comment.