| @@ -58,12 +58,15 @@ static const struct uverbs_attr_spec mlx5_ib_flow_type[] = { · 57 unmodified lines |
| 58 | 58 | }, |
| 59 | 59 | }; |
| 60 | 60 | |
| 61 | +#define MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS 2 |
| 61 | 62 | static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)( |
| 62 | 63 | struct ib_uverbs_file *file, struct uverbs_attr_bundle *attrs) |
| 63 | 64 | { |
| 64 | 65 | struct mlx5_flow_act flow_act = {.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG}; |
| 65 | 66 | struct mlx5_ib_flow_handler *flow_handler; |
| 66 | 67 | struct mlx5_ib_flow_matcher *fs_matcher; |
| 68 | + struct ib_uobject **arr_flow_actions; |
| 69 | + struct ib_uflow_resources *uflow_res; |
| 67 | 70 | void *devx_obj; |
| 68 | 71 | int dest_id, dest_type; |
| 69 | 72 | void *cmd_in; |
| @@ -73,6 +76,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)( · 3 unmodified lines |
| 73 | 76 | struct ib_uobject *uobj = |
| 74 | 77 | uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_CREATE_FLOW_HANDLE); |
| 75 | 78 | struct mlx5_ib_dev *dev = to_mdev(uobj->context->device); |
| 79 | + int len, ret, i; |
| 76 | 80 | |
| 77 | 81 | if (!capable(CAP_NET_RAW)) |
| 78 | 82 | return -EPERM; |
| @@ -124,15 +128,38 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)( · 45 unmodified lines |
| 124 | 128 | MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE); |
| 125 | 129 | fs_matcher = uverbs_attr_get_obj(attrs, |
| 126 | 130 | MLX5_IB_ATTR_CREATE_FLOW_MATCHER); |
| 131 | + |
| 132 | + uflow_res = flow_resources_alloc(MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS); |
| 133 | + if (!uflow_res) |
| 134 | + return -ENOMEM; |
| 135 | + |
| 136 | + len = uverbs_attr_get_uobjs_arr(attrs, |
| 137 | + MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS, &arr_flow_actions); |
| 138 | + for (i = 0; i < len; i++) { |
| 139 | + struct mlx5_ib_flow_action *maction = |
| 140 | + to_mflow_act(arr_flow_actions[i]->object); |
| 141 | + |
| 142 | + ret = parse_flow_flow_action(maction, false, &flow_act); |
| 143 | + if (ret) |
| 144 | + goto err_out; |
| 145 | + flow_resources_add(uflow_res, IB_FLOW_SPEC_ACTION_HANDLE, |
| 146 | + arr_flow_actions[i]->object); |
| 147 | + } |
| 148 | + |
| 127 | 149 | flow_handler = mlx5_ib_raw_fs_rule_add(dev, fs_matcher, &flow_act, |
| 128 | 150 | cmd_in, inlen, |
| 129 | 151 | dest_id, dest_type); |
| 130 | | − if (IS_ERR(flow_handler)) |
| 131 | | − return PTR_ERR(flow_handler); |
| 152 | + if (IS_ERR(flow_handler)) { |
| 153 | + ret = PTR_ERR(flow_handler); |
| 154 | + goto err_out; |
| 155 | + } |
| 132 | 156 | |
| 133 | | − ib_set_flow(uobj, &flow_handler->ibflow, qp, &dev->ib_dev, NULL); |
| 157 | + ib_set_flow(uobj, &flow_handler->ibflow, qp, &dev->ib_dev, uflow_res); |
| 134 | 158 | |
| 135 | 159 | return 0; |
| 160 | +err_out: |
| 161 | + ib_uverbs_flow_resources_free(uflow_res); |
| 162 | + return ret; |
| 136 | 163 | } |
| 137 | 164 | |
| 138 | 165 | static int flow_matcher_cleanup(struct ib_uobject *uobject, |
| @@ -459,7 +486,12 @@ DECLARE_UVERBS_NAMED_METHOD( · 320 unmodified lines |
| 459 | 486 | UVERBS_ACCESS_READ), |
| 460 | 487 | UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX, |
| 461 | 488 | MLX5_IB_OBJECT_DEVX_OBJ, |
| 462 | | − UVERBS_ACCESS_READ)); |
| 489 | + UVERBS_ACCESS_READ), |
| 490 | + UVERBS_ATTR_IDRS_ARR(MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS, |
| 491 | + UVERBS_OBJECT_FLOW_ACTION, |
| 492 | + UVERBS_ACCESS_READ, 1, |
| 493 | + MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS, |
| 494 | + UA_OPTIONAL)); |
| 463 | 495 | |
| 464 | 496 | DECLARE_UVERBS_NAMED_METHOD_DESTROY( |
| 465 | 497 | MLX5_IB_METHOD_DESTROY_FLOW, |