|
@@ -1089,6 +1089,30 @@ static int __mlx4_ib_destroy_flow(struct mlx4_dev *dev, u64 reg_id)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+static int mlx4_ib_tunnel_steer_add(struct ib_qp *qp, struct ib_flow_attr *flow_attr,
|
|
|
+ u64 *reg_id)
|
|
|
+{
|
|
|
+ void *ib_flow;
|
|
|
+ union ib_flow_spec *ib_spec;
|
|
|
+ struct mlx4_dev *dev = to_mdev(qp->device)->dev;
|
|
|
+ int err = 0;
|
|
|
+
|
|
|
+ if (dev->caps.tunnel_offload_mode != MLX4_TUNNEL_OFFLOAD_MODE_VXLAN)
|
|
|
+ return 0; /* do nothing */
|
|
|
+
|
|
|
+ ib_flow = flow_attr + 1;
|
|
|
+ ib_spec = (union ib_flow_spec *)ib_flow;
|
|
|
+
|
|
|
+ if (ib_spec->type != IB_FLOW_SPEC_ETH || flow_attr->num_of_specs != 1)
|
|
|
+ return 0; /* do nothing */
|
|
|
+
|
|
|
+ err = mlx4_tunnel_steer_add(to_mdev(qp->device)->dev, ib_spec->eth.val.dst_mac,
|
|
|
+ flow_attr->port, qp->qp_num,
|
|
|
+ MLX4_DOMAIN_UVERBS | (flow_attr->priority & 0xff),
|
|
|
+ reg_id);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
static struct ib_flow *mlx4_ib_create_flow(struct ib_qp *qp,
|
|
|
struct ib_flow_attr *flow_attr,
|
|
|
int domain)
|
|
@@ -1136,6 +1160,12 @@ static struct ib_flow *mlx4_ib_create_flow(struct ib_qp *qp,
|
|
|
i++;
|
|
|
}
|
|
|
|
|
|
+ if (i < ARRAY_SIZE(type) && flow_attr->type == IB_FLOW_ATTR_NORMAL) {
|
|
|
+ err = mlx4_ib_tunnel_steer_add(qp, flow_attr, &mflow->reg_id[i]);
|
|
|
+ if (err)
|
|
|
+ goto err_free;
|
|
|
+ }
|
|
|
+
|
|
|
return &mflow->ibflow;
|
|
|
|
|
|
err_free:
|