2 * Copyright (c) 2018, Mellanox Technologies inc. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34 #include <rdma/uverbs_std_types.h>
36 static int uverbs_free_flow_action(struct ib_uobject *uobject,
37 enum rdma_remove_reason why)
39 struct ib_flow_action *action = uobject->object;
41 if (why == RDMA_REMOVE_DESTROY &&
42 atomic_read(&action->usecnt))
45 return action->device->destroy_flow_action(action);
48 static u64 esp_flags_uverbs_to_verbs(struct uverbs_attr_bundle *attrs,
49 u32 flags, bool is_modify)
51 u64 verbs_flags = flags;
53 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_ESN))
54 verbs_flags |= IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED;
56 if (is_modify && uverbs_attr_is_valid(attrs,
57 UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS))
58 verbs_flags |= IB_FLOW_ACTION_ESP_FLAGS_MOD_ESP_ATTRS;
63 static int validate_flow_action_esp_keymat_aes_gcm(struct ib_flow_action_attrs_esp_keymats *keymat)
65 struct ib_uverbs_flow_action_esp_keymat_aes_gcm *aes_gcm =
66 &keymat->keymat.aes_gcm;
68 if (aes_gcm->iv_algo > IB_UVERBS_FLOW_ACTION_IV_ALGO_SEQ)
71 if (aes_gcm->key_len != 32 &&
72 aes_gcm->key_len != 24 &&
73 aes_gcm->key_len != 16)
76 if (aes_gcm->icv_len != 16 &&
77 aes_gcm->icv_len != 8 &&
78 aes_gcm->icv_len != 12)
84 static int (* const flow_action_esp_keymat_validate[])(struct ib_flow_action_attrs_esp_keymats *keymat) = {
85 [IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM] = validate_flow_action_esp_keymat_aes_gcm,
88 static int flow_action_esp_replay_none(struct ib_flow_action_attrs_esp_replays *replay,
91 /* This is used in order to modify an esp flow action with an enabled
92 * replay protection to a disabled one. This is only supported via
93 * modify, as in create verb we can simply drop the REPLAY attribute and
94 * achieve the same thing.
96 return is_modify ? 0 : -EINVAL;
99 static int flow_action_esp_replay_def_ok(struct ib_flow_action_attrs_esp_replays *replay,
102 /* Some replay protections could always be enabled without validating
108 static int (* const flow_action_esp_replay_validate[])(struct ib_flow_action_attrs_esp_replays *replay,
110 [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_NONE] = flow_action_esp_replay_none,
111 [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_BMP] = flow_action_esp_replay_def_ok,
114 static int parse_esp_ip(enum ib_flow_spec_type proto,
115 const void __user *val_ptr,
116 size_t len, union ib_flow_spec *out)
119 const struct ib_uverbs_flow_ipv4_filter ipv4 = {
120 .src_ip = cpu_to_be32(0xffffffffUL),
121 .dst_ip = cpu_to_be32(0xffffffffUL),
127 const struct ib_uverbs_flow_ipv6_filter ipv6 = {
128 .src_ip = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
129 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
130 .dst_ip = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
131 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
132 .flow_label = cpu_to_be32(0xffffffffUL),
134 .traffic_class = 0xff,
138 struct ib_uverbs_flow_ipv4_filter ipv4;
139 struct ib_uverbs_flow_ipv6_filter ipv6;
141 const void *user_pmask;
144 /* If the flow IPv4/IPv6 flow specifications are extended, the mask
145 * should be changed as well.
147 BUILD_BUG_ON(offsetof(struct ib_uverbs_flow_ipv4_filter, flags) +
148 sizeof(ipv4.flags) != sizeof(ipv4));
149 BUILD_BUG_ON(offsetof(struct ib_uverbs_flow_ipv6_filter, reserved) +
150 sizeof(ipv6.reserved) != sizeof(ipv6));
153 case IB_FLOW_SPEC_IPV4:
154 if (len > sizeof(user_val.ipv4) &&
155 !ib_is_buffer_cleared(val_ptr + sizeof(user_val.ipv4),
156 len - sizeof(user_val.ipv4)))
159 val_len = min_t(size_t, len, sizeof(user_val.ipv4));
160 ret = copy_from_user(&user_val.ipv4, val_ptr,
167 case IB_FLOW_SPEC_IPV6:
168 if (len > sizeof(user_val.ipv6) &&
169 !ib_is_buffer_cleared(val_ptr + sizeof(user_val.ipv6),
170 len - sizeof(user_val.ipv6)))
173 val_len = min_t(size_t, len, sizeof(user_val.ipv6));
174 ret = copy_from_user(&user_val.ipv6, val_ptr,
185 return ib_uverbs_kern_spec_to_ib_spec_filter(proto, user_pmask,
190 static int flow_action_esp_get_encap(struct ib_flow_spec_list *out,
191 struct uverbs_attr_bundle *attrs)
193 struct ib_uverbs_flow_action_esp_encap uverbs_encap;
196 ret = uverbs_copy_from(&uverbs_encap, attrs,
197 UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP);
201 /* We currently support only one encap */
202 if (uverbs_encap.next_ptr)
205 if (uverbs_encap.type != IB_FLOW_SPEC_IPV4 &&
206 uverbs_encap.type != IB_FLOW_SPEC_IPV6)
209 return parse_esp_ip(uverbs_encap.type,
210 u64_to_user_ptr(uverbs_encap.val_ptr),
215 struct ib_flow_action_esp_attr {
216 struct ib_flow_action_attrs_esp hdr;
217 struct ib_flow_action_attrs_esp_keymats keymat;
218 struct ib_flow_action_attrs_esp_replays replay;
219 /* We currently support only one spec */
220 struct ib_flow_spec_list encap;
223 #define ESP_LAST_SUPPORTED_FLAG IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW
224 static int parse_flow_action_esp(struct ib_device *ib_dev,
225 struct ib_uverbs_file *file,
226 struct uverbs_attr_bundle *attrs,
227 struct ib_flow_action_esp_attr *esp_attr,
230 struct ib_uverbs_flow_action_esp uverbs_esp = {};
233 /* Optional param, if it doesn't exist, we get -ENOENT and skip it */
234 ret = uverbs_copy_from(&esp_attr->hdr.esn, attrs,
235 UVERBS_ATTR_FLOW_ACTION_ESP_ESN);
236 if (IS_UVERBS_COPY_ERR(ret))
239 /* This can be called from FLOW_ACTION_ESP_MODIFY where
240 * UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS is optional
242 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS)) {
243 ret = uverbs_copy_from_or_zero(&uverbs_esp, attrs,
244 UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS);
248 if (uverbs_esp.flags & ~((ESP_LAST_SUPPORTED_FLAG << 1) - 1))
251 esp_attr->hdr.spi = uverbs_esp.spi;
252 esp_attr->hdr.seq = uverbs_esp.seq;
253 esp_attr->hdr.tfc_pad = uverbs_esp.tfc_pad;
254 esp_attr->hdr.hard_limit_pkts = uverbs_esp.hard_limit_pkts;
256 esp_attr->hdr.flags = esp_flags_uverbs_to_verbs(attrs, uverbs_esp.flags,
259 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT)) {
260 esp_attr->keymat.protocol =
261 uverbs_attr_get_enum_id(attrs,
262 UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT);
263 ret = uverbs_copy_from_or_zero(&esp_attr->keymat.keymat,
265 UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT);
269 ret = flow_action_esp_keymat_validate[esp_attr->keymat.protocol](&esp_attr->keymat);
273 esp_attr->hdr.keymat = &esp_attr->keymat;
276 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY)) {
277 esp_attr->replay.protocol =
278 uverbs_attr_get_enum_id(attrs,
279 UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY);
281 ret = uverbs_copy_from_or_zero(&esp_attr->replay.replay,
283 UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY);
287 ret = flow_action_esp_replay_validate[esp_attr->replay.protocol](&esp_attr->replay,
292 esp_attr->hdr.replay = &esp_attr->replay;
295 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP)) {
296 ret = flow_action_esp_get_encap(&esp_attr->encap, attrs);
300 esp_attr->hdr.encap = &esp_attr->encap;
306 static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE)(struct ib_device *ib_dev,
307 struct ib_uverbs_file *file,
308 struct uverbs_attr_bundle *attrs)
311 struct ib_uobject *uobj;
312 struct ib_flow_action *action;
313 struct ib_flow_action_esp_attr esp_attr = {};
315 if (!ib_dev->create_flow_action_esp)
318 ret = parse_flow_action_esp(ib_dev, file, attrs, &esp_attr, false);
322 /* No need to check as this attribute is marked as MANDATORY */
323 uobj = uverbs_attr_get(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_HANDLE)->obj_attr.uobject;
324 action = ib_dev->create_flow_action_esp(ib_dev, &esp_attr.hdr, attrs);
326 return PTR_ERR(action);
328 atomic_set(&action->usecnt, 0);
329 action->device = ib_dev;
330 action->type = IB_FLOW_ACTION_ESP;
331 action->uobject = uobj;
332 uobj->object = action;
337 static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY)(struct ib_device *ib_dev,
338 struct ib_uverbs_file *file,
339 struct uverbs_attr_bundle *attrs)
342 struct ib_uobject *uobj;
343 struct ib_flow_action *action;
344 struct ib_flow_action_esp_attr esp_attr = {};
346 if (!ib_dev->modify_flow_action_esp)
349 ret = parse_flow_action_esp(ib_dev, file, attrs, &esp_attr, true);
353 uobj = uverbs_attr_get(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_HANDLE)->obj_attr.uobject;
354 action = uobj->object;
356 if (action->type != IB_FLOW_ACTION_ESP)
359 return ib_dev->modify_flow_action_esp(action,
364 static const struct uverbs_attr_spec uverbs_flow_action_esp_keymat[] = {
365 [IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM] = {
367 .type = UVERBS_ATTR_TYPE_PTR_IN,
368 UVERBS_ATTR_TYPE(struct ib_uverbs_flow_action_esp_keymat_aes_gcm),
369 .flags = UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO,
374 static const struct uverbs_attr_spec uverbs_flow_action_esp_replay[] = {
375 [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_NONE] = {
377 .type = UVERBS_ATTR_TYPE_PTR_IN,
378 /* No need to specify any data */
382 [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_BMP] = {
384 .type = UVERBS_ATTR_TYPE_PTR_IN,
385 UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp_replay_bmp, size),
386 .flags = UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO,
391 static DECLARE_UVERBS_NAMED_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE,
392 &UVERBS_ATTR_IDR(UVERBS_ATTR_FLOW_ACTION_ESP_HANDLE, UVERBS_OBJECT_FLOW_ACTION,
394 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
395 &UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS,
396 UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp, hard_limit_pkts),
397 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
398 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO)),
399 &UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ESN, UVERBS_ATTR_TYPE(__u32)),
400 &UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT,
401 uverbs_flow_action_esp_keymat,
402 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
403 &UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY,
404 uverbs_flow_action_esp_replay),
405 &UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP,
406 UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp_encap, type)));
408 static DECLARE_UVERBS_NAMED_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY,
409 &UVERBS_ATTR_IDR(UVERBS_ATTR_FLOW_ACTION_ESP_HANDLE, UVERBS_OBJECT_FLOW_ACTION,
411 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
412 &UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS,
413 UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp, hard_limit_pkts),
414 UA_FLAGS(UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO)),
415 &UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ESN, UVERBS_ATTR_TYPE(__u32)),
416 &UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT,
417 uverbs_flow_action_esp_keymat),
418 &UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY,
419 uverbs_flow_action_esp_replay),
420 &UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP,
421 UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp_encap, type)));
423 static DECLARE_UVERBS_NAMED_METHOD_WITH_HANDLER(UVERBS_METHOD_FLOW_ACTION_DESTROY,
424 uverbs_destroy_def_handler,
425 &UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_FLOW_ACTION_HANDLE,
426 UVERBS_OBJECT_FLOW_ACTION,
427 UVERBS_ACCESS_DESTROY,
428 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
430 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_FLOW_ACTION,
431 &UVERBS_TYPE_ALLOC_IDR(0, uverbs_free_flow_action),
432 &UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE),
433 &UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_DESTROY),
434 &UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY));