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
33 #include "rdma_core.h"
35 #include <rdma/uverbs_std_types.h>
37 static int uverbs_free_flow_action(struct ib_uobject *uobject,
38 enum rdma_remove_reason why,
39 struct uverbs_attr_bundle *attrs)
41 struct ib_flow_action *action = uobject->object;
44 ret = ib_destroy_usecnt(&action->usecnt, why, uobject);
48 return action->device->ops.destroy_flow_action(action);
51 static u64 esp_flags_uverbs_to_verbs(struct uverbs_attr_bundle *attrs,
52 u32 flags, bool is_modify)
54 u64 verbs_flags = flags;
56 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_ESN))
57 verbs_flags |= IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED;
59 if (is_modify && uverbs_attr_is_valid(attrs,
60 UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS))
61 verbs_flags |= IB_FLOW_ACTION_ESP_FLAGS_MOD_ESP_ATTRS;
66 static int validate_flow_action_esp_keymat_aes_gcm(struct ib_flow_action_attrs_esp_keymats *keymat)
68 struct ib_uverbs_flow_action_esp_keymat_aes_gcm *aes_gcm =
69 &keymat->keymat.aes_gcm;
71 if (aes_gcm->iv_algo > IB_UVERBS_FLOW_ACTION_IV_ALGO_SEQ)
74 if (aes_gcm->key_len != 32 &&
75 aes_gcm->key_len != 24 &&
76 aes_gcm->key_len != 16)
79 if (aes_gcm->icv_len != 16 &&
80 aes_gcm->icv_len != 8 &&
81 aes_gcm->icv_len != 12)
87 static int (* const flow_action_esp_keymat_validate[])(struct ib_flow_action_attrs_esp_keymats *keymat) = {
88 [IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM] = validate_flow_action_esp_keymat_aes_gcm,
91 static int flow_action_esp_replay_none(struct ib_flow_action_attrs_esp_replays *replay,
94 /* This is used in order to modify an esp flow action with an enabled
95 * replay protection to a disabled one. This is only supported via
96 * modify, as in create verb we can simply drop the REPLAY attribute and
97 * achieve the same thing.
99 return is_modify ? 0 : -EINVAL;
102 static int flow_action_esp_replay_def_ok(struct ib_flow_action_attrs_esp_replays *replay,
105 /* Some replay protections could always be enabled without validating
111 static int (* const flow_action_esp_replay_validate[])(struct ib_flow_action_attrs_esp_replays *replay,
113 [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_NONE] = flow_action_esp_replay_none,
114 [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_BMP] = flow_action_esp_replay_def_ok,
117 static int parse_esp_ip(enum ib_flow_spec_type proto,
118 const void __user *val_ptr,
119 size_t len, union ib_flow_spec *out)
122 const struct ib_uverbs_flow_ipv4_filter ipv4 = {
123 .src_ip = cpu_to_be32(0xffffffffUL),
124 .dst_ip = cpu_to_be32(0xffffffffUL),
130 const struct ib_uverbs_flow_ipv6_filter ipv6 = {
131 .src_ip = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
132 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
133 .dst_ip = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
134 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
135 .flow_label = cpu_to_be32(0xffffffffUL),
137 .traffic_class = 0xff,
141 struct ib_uverbs_flow_ipv4_filter ipv4;
142 struct ib_uverbs_flow_ipv6_filter ipv6;
144 const void *user_pmask;
147 /* If the flow IPv4/IPv6 flow specifications are extended, the mask
148 * should be changed as well.
150 BUILD_BUG_ON(offsetof(struct ib_uverbs_flow_ipv4_filter, flags) +
151 sizeof(ipv4.flags) != sizeof(ipv4));
152 BUILD_BUG_ON(offsetof(struct ib_uverbs_flow_ipv6_filter, reserved) +
153 sizeof(ipv6.reserved) != sizeof(ipv6));
156 case IB_FLOW_SPEC_IPV4:
157 if (len > sizeof(user_val.ipv4) &&
158 !ib_is_buffer_cleared(val_ptr + sizeof(user_val.ipv4),
159 len - sizeof(user_val.ipv4)))
162 val_len = min_t(size_t, len, sizeof(user_val.ipv4));
163 ret = copy_from_user(&user_val.ipv4, val_ptr,
170 case IB_FLOW_SPEC_IPV6:
171 if (len > sizeof(user_val.ipv6) &&
172 !ib_is_buffer_cleared(val_ptr + sizeof(user_val.ipv6),
173 len - sizeof(user_val.ipv6)))
176 val_len = min_t(size_t, len, sizeof(user_val.ipv6));
177 ret = copy_from_user(&user_val.ipv6, val_ptr,
188 return ib_uverbs_kern_spec_to_ib_spec_filter(proto, user_pmask,
193 static int flow_action_esp_get_encap(struct ib_flow_spec_list *out,
194 struct uverbs_attr_bundle *attrs)
196 struct ib_uverbs_flow_action_esp_encap uverbs_encap;
199 ret = uverbs_copy_from(&uverbs_encap, attrs,
200 UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP);
204 /* We currently support only one encap */
205 if (uverbs_encap.next_ptr)
208 if (uverbs_encap.type != IB_FLOW_SPEC_IPV4 &&
209 uverbs_encap.type != IB_FLOW_SPEC_IPV6)
212 return parse_esp_ip(uverbs_encap.type,
213 u64_to_user_ptr(uverbs_encap.val_ptr),
218 struct ib_flow_action_esp_attr {
219 struct ib_flow_action_attrs_esp hdr;
220 struct ib_flow_action_attrs_esp_keymats keymat;
221 struct ib_flow_action_attrs_esp_replays replay;
222 /* We currently support only one spec */
223 struct ib_flow_spec_list encap;
226 #define ESP_LAST_SUPPORTED_FLAG IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW
227 static int parse_flow_action_esp(struct ib_device *ib_dev,
228 struct uverbs_attr_bundle *attrs,
229 struct ib_flow_action_esp_attr *esp_attr,
232 struct ib_uverbs_flow_action_esp uverbs_esp = {};
235 /* Optional param, if it doesn't exist, we get -ENOENT and skip it */
236 ret = uverbs_copy_from(&esp_attr->hdr.esn, attrs,
237 UVERBS_ATTR_FLOW_ACTION_ESP_ESN);
238 if (IS_UVERBS_COPY_ERR(ret))
241 /* This can be called from FLOW_ACTION_ESP_MODIFY where
242 * UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS is optional
244 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS)) {
245 ret = uverbs_copy_from_or_zero(&uverbs_esp, attrs,
246 UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS);
250 if (uverbs_esp.flags & ~((ESP_LAST_SUPPORTED_FLAG << 1) - 1))
253 esp_attr->hdr.spi = uverbs_esp.spi;
254 esp_attr->hdr.seq = uverbs_esp.seq;
255 esp_attr->hdr.tfc_pad = uverbs_esp.tfc_pad;
256 esp_attr->hdr.hard_limit_pkts = uverbs_esp.hard_limit_pkts;
258 esp_attr->hdr.flags = esp_flags_uverbs_to_verbs(attrs, uverbs_esp.flags,
261 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT)) {
262 esp_attr->keymat.protocol =
263 uverbs_attr_get_enum_id(attrs,
264 UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT);
265 ret = uverbs_copy_from_or_zero(&esp_attr->keymat.keymat,
267 UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT);
271 ret = flow_action_esp_keymat_validate[esp_attr->keymat.protocol](&esp_attr->keymat);
275 esp_attr->hdr.keymat = &esp_attr->keymat;
278 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY)) {
279 esp_attr->replay.protocol =
280 uverbs_attr_get_enum_id(attrs,
281 UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY);
283 ret = uverbs_copy_from_or_zero(&esp_attr->replay.replay,
285 UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY);
289 ret = flow_action_esp_replay_validate[esp_attr->replay.protocol](&esp_attr->replay,
294 esp_attr->hdr.replay = &esp_attr->replay;
297 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP)) {
298 ret = flow_action_esp_get_encap(&esp_attr->encap, attrs);
302 esp_attr->hdr.encap = &esp_attr->encap;
308 static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE)(
309 struct uverbs_attr_bundle *attrs)
311 struct ib_uobject *uobj = uverbs_attr_get_uobject(
312 attrs, UVERBS_ATTR_CREATE_FLOW_ACTION_ESP_HANDLE);
313 struct ib_device *ib_dev = attrs->context->device;
315 struct ib_flow_action *action;
316 struct ib_flow_action_esp_attr esp_attr = {};
318 if (!ib_dev->ops.create_flow_action_esp)
321 ret = parse_flow_action_esp(ib_dev, attrs, &esp_attr, false);
325 /* No need to check as this attribute is marked as MANDATORY */
326 action = ib_dev->ops.create_flow_action_esp(ib_dev, &esp_attr.hdr,
329 return PTR_ERR(action);
331 uverbs_flow_action_fill_action(action, uobj, ib_dev,
337 static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY)(
338 struct uverbs_attr_bundle *attrs)
340 struct ib_uobject *uobj = uverbs_attr_get_uobject(
341 attrs, UVERBS_ATTR_MODIFY_FLOW_ACTION_ESP_HANDLE);
342 struct ib_flow_action *action = uobj->object;
344 struct ib_flow_action_esp_attr esp_attr = {};
346 if (!action->device->ops.modify_flow_action_esp)
349 ret = parse_flow_action_esp(action->device, attrs, &esp_attr, true);
353 if (action->type != IB_FLOW_ACTION_ESP)
356 return action->device->ops.modify_flow_action_esp(action,
361 static const struct uverbs_attr_spec uverbs_flow_action_esp_keymat[] = {
362 [IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM] = {
363 .type = UVERBS_ATTR_TYPE_PTR_IN,
365 struct ib_uverbs_flow_action_esp_keymat_aes_gcm,
370 static const struct uverbs_attr_spec uverbs_flow_action_esp_replay[] = {
371 [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_NONE] = {
372 .type = UVERBS_ATTR_TYPE_PTR_IN,
373 UVERBS_ATTR_NO_DATA(),
375 [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_BMP] = {
376 .type = UVERBS_ATTR_TYPE_PTR_IN,
377 UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp_replay_bmp,
382 DECLARE_UVERBS_NAMED_METHOD(
383 UVERBS_METHOD_FLOW_ACTION_ESP_CREATE,
384 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_FLOW_ACTION_ESP_HANDLE,
385 UVERBS_OBJECT_FLOW_ACTION,
388 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS,
389 UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp,
392 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ESN,
393 UVERBS_ATTR_TYPE(__u32),
395 UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT,
396 uverbs_flow_action_esp_keymat,
398 UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY,
399 uverbs_flow_action_esp_replay,
402 UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP,
403 UVERBS_ATTR_TYPE(struct ib_uverbs_flow_action_esp_encap),
406 DECLARE_UVERBS_NAMED_METHOD(
407 UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY,
408 UVERBS_ATTR_IDR(UVERBS_ATTR_MODIFY_FLOW_ACTION_ESP_HANDLE,
409 UVERBS_OBJECT_FLOW_ACTION,
412 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS,
413 UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp,
416 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ESN,
417 UVERBS_ATTR_TYPE(__u32),
419 UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT,
420 uverbs_flow_action_esp_keymat,
422 UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY,
423 uverbs_flow_action_esp_replay,
426 UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP,
427 UVERBS_ATTR_TYPE(struct ib_uverbs_flow_action_esp_encap),
430 DECLARE_UVERBS_NAMED_METHOD_DESTROY(
431 UVERBS_METHOD_FLOW_ACTION_DESTROY,
432 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_FLOW_ACTION_HANDLE,
433 UVERBS_OBJECT_FLOW_ACTION,
434 UVERBS_ACCESS_DESTROY,
437 DECLARE_UVERBS_NAMED_OBJECT(
438 UVERBS_OBJECT_FLOW_ACTION,
439 UVERBS_TYPE_ALLOC_IDR(uverbs_free_flow_action),
440 &UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE),
441 &UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_DESTROY),
442 &UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY));
444 const struct uapi_definition uverbs_def_obj_flow_action[] = {
445 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
446 UVERBS_OBJECT_FLOW_ACTION,
447 UAPI_DEF_OBJ_NEEDS_FN(destroy_flow_action)),