OSDN Git Service

b4422e4def17d09ea84fb088cd0711951cb3d9d2
[tomoyo/tomoyo-test1.git] / drivers / infiniband / hw / mlx5 / flow.c
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /*
3  * Copyright (c) 2018, Mellanox Technologies inc.  All rights reserved.
4  */
5
6 #include <rdma/ib_user_verbs.h>
7 #include <rdma/ib_verbs.h>
8 #include <rdma/uverbs_types.h>
9 #include <rdma/uverbs_ioctl.h>
10 #include <rdma/mlx5_user_ioctl_cmds.h>
11 #include <rdma/ib_umem.h>
12 #include <linux/mlx5/driver.h>
13 #include <linux/mlx5/fs.h>
14 #include "mlx5_ib.h"
15
16 #define UVERBS_MODULE_NAME mlx5_ib
17 #include <rdma/uverbs_named_ioctl.h>
18
19 static const struct uverbs_attr_spec mlx5_ib_flow_type[] = {
20         [MLX5_IB_FLOW_TYPE_NORMAL] = {
21                 .type = UVERBS_ATTR_TYPE_PTR_IN,
22                 .u.ptr = {
23                         .len = sizeof(u16), /* data is priority */
24                         .min_len = sizeof(u16),
25                 }
26         },
27         [MLX5_IB_FLOW_TYPE_SNIFFER] = {
28                 .type = UVERBS_ATTR_TYPE_PTR_IN,
29                 UVERBS_ATTR_NO_DATA(),
30         },
31         [MLX5_IB_FLOW_TYPE_ALL_DEFAULT] = {
32                 .type = UVERBS_ATTR_TYPE_PTR_IN,
33                 UVERBS_ATTR_NO_DATA(),
34         },
35         [MLX5_IB_FLOW_TYPE_MC_DEFAULT] = {
36                 .type = UVERBS_ATTR_TYPE_PTR_IN,
37                 UVERBS_ATTR_NO_DATA(),
38         },
39 };
40
41 static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
42         struct ib_device *ib_dev, struct ib_uverbs_file *file,
43         struct uverbs_attr_bundle *attrs)
44 {
45         struct mlx5_ib_flow_handler *flow_handler;
46         struct mlx5_ib_flow_matcher *fs_matcher;
47         void *devx_obj;
48         int dest_id, dest_type;
49         void *cmd_in;
50         int inlen;
51         bool dest_devx, dest_qp;
52         struct ib_qp *qp = NULL;
53         struct ib_uobject *uobj =
54                 uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_CREATE_FLOW_HANDLE);
55         struct mlx5_ib_dev *dev = to_mdev(uobj->context->device);
56
57         if (!capable(CAP_NET_RAW))
58                 return -EPERM;
59
60         dest_devx =
61                 uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX);
62         dest_qp = uverbs_attr_is_valid(attrs,
63                                        MLX5_IB_ATTR_CREATE_FLOW_DEST_QP);
64
65         if ((dest_devx && dest_qp) || (!dest_devx && !dest_qp))
66                 return -EINVAL;
67
68         if (dest_devx) {
69                 devx_obj = uverbs_attr_get_obj(
70                         attrs, MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX);
71                 if (IS_ERR(devx_obj))
72                         return PTR_ERR(devx_obj);
73
74                 /* Verify that the given DEVX object is a flow
75                  * steering destination.
76                  */
77                 if (!mlx5_ib_devx_is_flow_dest(devx_obj, &dest_id, &dest_type))
78                         return -EINVAL;
79         } else {
80                 struct mlx5_ib_qp *mqp;
81
82                 qp = uverbs_attr_get_obj(attrs,
83                                          MLX5_IB_ATTR_CREATE_FLOW_DEST_QP);
84                 if (IS_ERR(qp))
85                         return PTR_ERR(qp);
86
87                 if (qp->qp_type != IB_QPT_RAW_PACKET)
88                         return -EINVAL;
89
90                 mqp = to_mqp(qp);
91                 if (mqp->flags & MLX5_IB_QP_RSS)
92                         dest_id = mqp->rss_qp.tirn;
93                 else
94                         dest_id = mqp->raw_packet_qp.rq.tirn;
95                 dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR;
96         }
97
98         if (dev->rep)
99                 return -ENOTSUPP;
100
101         cmd_in = uverbs_attr_get_alloced_ptr(
102                 attrs, MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
103         inlen = uverbs_attr_get_len(attrs,
104                                     MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
105         fs_matcher = uverbs_attr_get_obj(attrs,
106                                          MLX5_IB_ATTR_CREATE_FLOW_MATCHER);
107         flow_handler = mlx5_ib_raw_fs_rule_add(dev, fs_matcher, cmd_in, inlen,
108                                                dest_id, dest_type);
109         if (IS_ERR(flow_handler))
110                 return PTR_ERR(flow_handler);
111
112         ib_set_flow(uobj, &flow_handler->ibflow, qp, ib_dev);
113
114         return 0;
115 }
116
117 static int flow_matcher_cleanup(struct ib_uobject *uobject,
118                                 enum rdma_remove_reason why)
119 {
120         struct mlx5_ib_flow_matcher *obj = uobject->object;
121         int ret;
122
123         ret = ib_destroy_usecnt(&obj->usecnt, why, uobject);
124         if (ret)
125                 return ret;
126
127         kfree(obj);
128         return 0;
129 }
130
131 static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_MATCHER_CREATE)(
132         struct ib_device *ib_dev, struct ib_uverbs_file *file,
133         struct uverbs_attr_bundle *attrs)
134 {
135         struct ib_uobject *uobj = uverbs_attr_get_uobject(
136                 attrs, MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE);
137         struct mlx5_ib_dev *dev = to_mdev(uobj->context->device);
138         struct mlx5_ib_flow_matcher *obj;
139         int err;
140
141         obj = kzalloc(sizeof(struct mlx5_ib_flow_matcher), GFP_KERNEL);
142         if (!obj)
143                 return -ENOMEM;
144
145         obj->mask_len = uverbs_attr_get_len(
146                 attrs, MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK);
147         err = uverbs_copy_from(&obj->matcher_mask,
148                                attrs,
149                                MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK);
150         if (err)
151                 goto end;
152
153         obj->flow_type = uverbs_attr_get_enum_id(
154                 attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE);
155
156         if (obj->flow_type == MLX5_IB_FLOW_TYPE_NORMAL) {
157                 err = uverbs_copy_from(&obj->priority,
158                                        attrs,
159                                        MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE);
160                 if (err)
161                         goto end;
162         }
163
164         err = uverbs_copy_from(&obj->match_criteria_enable,
165                                attrs,
166                                MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA);
167         if (err)
168                 goto end;
169
170         uobj->object = obj;
171         obj->mdev = dev->mdev;
172         atomic_set(&obj->usecnt, 0);
173         return 0;
174
175 end:
176         kfree(obj);
177         return err;
178 }
179
180 DECLARE_UVERBS_NAMED_METHOD(
181         MLX5_IB_METHOD_CREATE_FLOW,
182         UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE,
183                         UVERBS_OBJECT_FLOW,
184                         UVERBS_ACCESS_NEW,
185                         UA_MANDATORY),
186         UVERBS_ATTR_PTR_IN(
187                 MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE,
188                 UVERBS_ATTR_SIZE(1, sizeof(struct mlx5_ib_match_params)),
189                 UA_MANDATORY,
190                 UA_ALLOC_AND_COPY),
191         UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_MATCHER,
192                         MLX5_IB_OBJECT_FLOW_MATCHER,
193                         UVERBS_ACCESS_READ,
194                         UA_MANDATORY),
195         UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_QP,
196                         UVERBS_OBJECT_QP,
197                         UVERBS_ACCESS_READ),
198         UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX,
199                         MLX5_IB_OBJECT_DEVX_OBJ,
200                         UVERBS_ACCESS_READ));
201
202 DECLARE_UVERBS_NAMED_METHOD_DESTROY(
203         MLX5_IB_METHOD_DESTROY_FLOW,
204         UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE,
205                         UVERBS_OBJECT_FLOW,
206                         UVERBS_ACCESS_DESTROY,
207                         UA_MANDATORY));
208
209 ADD_UVERBS_METHODS(mlx5_ib_fs,
210                    UVERBS_OBJECT_FLOW,
211                    &UVERBS_METHOD(MLX5_IB_METHOD_CREATE_FLOW),
212                    &UVERBS_METHOD(MLX5_IB_METHOD_DESTROY_FLOW));
213
214 DECLARE_UVERBS_NAMED_METHOD(
215         MLX5_IB_METHOD_FLOW_MATCHER_CREATE,
216         UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE,
217                         MLX5_IB_OBJECT_FLOW_MATCHER,
218                         UVERBS_ACCESS_NEW,
219                         UA_MANDATORY),
220         UVERBS_ATTR_PTR_IN(
221                 MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK,
222                 UVERBS_ATTR_SIZE(1, sizeof(struct mlx5_ib_match_params)),
223                 UA_MANDATORY),
224         UVERBS_ATTR_ENUM_IN(MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE,
225                             mlx5_ib_flow_type,
226                             UA_MANDATORY),
227         UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA,
228                            UVERBS_ATTR_TYPE(u8),
229                            UA_MANDATORY));
230
231 DECLARE_UVERBS_NAMED_METHOD_DESTROY(
232         MLX5_IB_METHOD_FLOW_MATCHER_DESTROY,
233         UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_DESTROY_HANDLE,
234                         MLX5_IB_OBJECT_FLOW_MATCHER,
235                         UVERBS_ACCESS_DESTROY,
236                         UA_MANDATORY));
237
238 DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_FLOW_MATCHER,
239                             UVERBS_TYPE_ALLOC_IDR(flow_matcher_cleanup),
240                             &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_CREATE),
241                             &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_DESTROY));
242
243 DECLARE_UVERBS_OBJECT_TREE(flow_objects,
244                            &UVERBS_OBJECT(MLX5_IB_OBJECT_FLOW_MATCHER));