IB/uverbs: Add support for flow counters
The struct ib_uverbs_flow_spec_action_count associates a counters object with the flow. Post this association the flow counters can be read via the counters object. Reviewed-by: Yishai Hadas <yishaih@mellanox.com> Signed-off-by: Raed Salem <raeds@mellanox.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
parent
7eea23a5cd
commit
b6ba4a9aa5
|
@ -263,6 +263,7 @@ struct ib_uverbs_flow_spec {
|
|||
struct ib_uverbs_flow_spec_action_tag flow_tag;
|
||||
struct ib_uverbs_flow_spec_action_drop drop;
|
||||
struct ib_uverbs_flow_spec_action_handle action;
|
||||
struct ib_uverbs_flow_spec_action_count flow_count;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -2742,43 +2742,82 @@ out_put:
|
|||
struct ib_uflow_resources {
|
||||
size_t max;
|
||||
size_t num;
|
||||
struct ib_flow_action *collection[0];
|
||||
size_t collection_num;
|
||||
size_t counters_num;
|
||||
struct ib_counters **counters;
|
||||
struct ib_flow_action **collection;
|
||||
};
|
||||
|
||||
static struct ib_uflow_resources *flow_resources_alloc(size_t num_specs)
|
||||
{
|
||||
struct ib_uflow_resources *resources;
|
||||
|
||||
resources =
|
||||
kmalloc(sizeof(*resources) +
|
||||
num_specs * sizeof(*resources->collection), GFP_KERNEL);
|
||||
resources = kzalloc(sizeof(*resources), GFP_KERNEL);
|
||||
|
||||
if (!resources)
|
||||
return NULL;
|
||||
goto err_res;
|
||||
|
||||
resources->counters =
|
||||
kcalloc(num_specs, sizeof(*resources->counters), GFP_KERNEL);
|
||||
|
||||
if (!resources->counters)
|
||||
goto err_cnt;
|
||||
|
||||
resources->collection =
|
||||
kcalloc(num_specs, sizeof(*resources->collection), GFP_KERNEL);
|
||||
|
||||
if (!resources->collection)
|
||||
goto err_collection;
|
||||
|
||||
resources->num = 0;
|
||||
resources->max = num_specs;
|
||||
|
||||
return resources;
|
||||
|
||||
err_collection:
|
||||
kfree(resources->counters);
|
||||
err_cnt:
|
||||
kfree(resources);
|
||||
err_res:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ib_uverbs_flow_resources_free(struct ib_uflow_resources *uflow_res)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < uflow_res->num; i++)
|
||||
for (i = 0; i < uflow_res->collection_num; i++)
|
||||
atomic_dec(&uflow_res->collection[i]->usecnt);
|
||||
|
||||
for (i = 0; i < uflow_res->counters_num; i++)
|
||||
atomic_dec(&uflow_res->counters[i]->usecnt);
|
||||
|
||||
kfree(uflow_res->collection);
|
||||
kfree(uflow_res->counters);
|
||||
kfree(uflow_res);
|
||||
}
|
||||
|
||||
static void flow_resources_add(struct ib_uflow_resources *uflow_res,
|
||||
struct ib_flow_action *action)
|
||||
enum ib_flow_spec_type type,
|
||||
void *ibobj)
|
||||
{
|
||||
WARN_ON(uflow_res->num >= uflow_res->max);
|
||||
|
||||
atomic_inc(&action->usecnt);
|
||||
uflow_res->collection[uflow_res->num++] = action;
|
||||
switch (type) {
|
||||
case IB_FLOW_SPEC_ACTION_HANDLE:
|
||||
atomic_inc(&((struct ib_flow_action *)ibobj)->usecnt);
|
||||
uflow_res->collection[uflow_res->collection_num++] =
|
||||
(struct ib_flow_action *)ibobj;
|
||||
break;
|
||||
case IB_FLOW_SPEC_ACTION_COUNT:
|
||||
atomic_inc(&((struct ib_counters *)ibobj)->usecnt);
|
||||
uflow_res->counters[uflow_res->counters_num++] =
|
||||
(struct ib_counters *)ibobj;
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
uflow_res->num++;
|
||||
}
|
||||
|
||||
static int kern_spec_to_ib_spec_action(struct ib_ucontext *ucontext,
|
||||
|
@ -2815,9 +2854,29 @@ static int kern_spec_to_ib_spec_action(struct ib_ucontext *ucontext,
|
|||
return -EINVAL;
|
||||
ib_spec->action.size =
|
||||
sizeof(struct ib_flow_spec_action_handle);
|
||||
flow_resources_add(uflow_res, ib_spec->action.act);
|
||||
flow_resources_add(uflow_res,
|
||||
IB_FLOW_SPEC_ACTION_HANDLE,
|
||||
ib_spec->action.act);
|
||||
uobj_put_obj_read(ib_spec->action.act);
|
||||
break;
|
||||
case IB_FLOW_SPEC_ACTION_COUNT:
|
||||
if (kern_spec->flow_count.size !=
|
||||
sizeof(struct ib_uverbs_flow_spec_action_count))
|
||||
return -EINVAL;
|
||||
ib_spec->flow_count.counters =
|
||||
uobj_get_obj_read(counters,
|
||||
UVERBS_OBJECT_COUNTERS,
|
||||
kern_spec->flow_count.handle,
|
||||
ucontext);
|
||||
if (!ib_spec->flow_count.counters)
|
||||
return -EINVAL;
|
||||
ib_spec->flow_count.size =
|
||||
sizeof(struct ib_flow_spec_action_count);
|
||||
flow_resources_add(uflow_res,
|
||||
IB_FLOW_SPEC_ACTION_COUNT,
|
||||
ib_spec->flow_count.counters);
|
||||
uobj_put_obj_read(ib_spec->flow_count.counters);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -998,6 +998,19 @@ struct ib_uverbs_flow_spec_action_handle {
|
|||
__u32 reserved1;
|
||||
};
|
||||
|
||||
struct ib_uverbs_flow_spec_action_count {
|
||||
union {
|
||||
struct ib_uverbs_flow_spec_hdr hdr;
|
||||
struct {
|
||||
__u32 type;
|
||||
__u16 size;
|
||||
__u16 reserved;
|
||||
};
|
||||
};
|
||||
__u32 handle;
|
||||
__u32 reserved1;
|
||||
};
|
||||
|
||||
struct ib_uverbs_flow_tunnel_filter {
|
||||
__be32 tunnel_id;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue