Skip to content

Commit

Permalink
IB/uverbs: Add support for flow counters
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Raed Salem authored and Leon Romanovsky committed Jun 2, 2018
1 parent 7eea23a commit b6ba4a9
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 11 deletions.
1 change: 1 addition & 0 deletions drivers/infiniband/core/uverbs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
};

Expand Down
81 changes: 70 additions & 11 deletions drivers/infiniband/core/uverbs_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2742,43 +2742,82 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
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,
Expand Down Expand Up @@ -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;
}
Expand Down
13 changes: 13 additions & 0 deletions include/uapi/rdma/ib_user_verbs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down

0 comments on commit b6ba4a9

Please sign in to comment.