Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Raed Salem and committed by
Leon Romanovsky
b6ba4a9a 7eea23a5

+84 -11
+1
drivers/infiniband/core/uverbs.h
··· 263 263 struct ib_uverbs_flow_spec_action_tag flow_tag; 264 264 struct ib_uverbs_flow_spec_action_drop drop; 265 265 struct ib_uverbs_flow_spec_action_handle action; 266 + struct ib_uverbs_flow_spec_action_count flow_count; 266 267 }; 267 268 }; 268 269
+70 -11
drivers/infiniband/core/uverbs_cmd.c
··· 2742 2742 struct ib_uflow_resources { 2743 2743 size_t max; 2744 2744 size_t num; 2745 - struct ib_flow_action *collection[0]; 2745 + size_t collection_num; 2746 + size_t counters_num; 2747 + struct ib_counters **counters; 2748 + struct ib_flow_action **collection; 2746 2749 }; 2747 2750 2748 2751 static struct ib_uflow_resources *flow_resources_alloc(size_t num_specs) 2749 2752 { 2750 2753 struct ib_uflow_resources *resources; 2751 2754 2752 - resources = 2753 - kmalloc(sizeof(*resources) + 2754 - num_specs * sizeof(*resources->collection), GFP_KERNEL); 2755 + resources = kzalloc(sizeof(*resources), GFP_KERNEL); 2755 2756 2756 2757 if (!resources) 2757 - return NULL; 2758 + goto err_res; 2758 2759 2759 - resources->num = 0; 2760 + resources->counters = 2761 + kcalloc(num_specs, sizeof(*resources->counters), GFP_KERNEL); 2762 + 2763 + if (!resources->counters) 2764 + goto err_cnt; 2765 + 2766 + resources->collection = 2767 + kcalloc(num_specs, sizeof(*resources->collection), GFP_KERNEL); 2768 + 2769 + if (!resources->collection) 2770 + goto err_collection; 2771 + 2760 2772 resources->max = num_specs; 2761 2773 2762 2774 return resources; 2775 + 2776 + err_collection: 2777 + kfree(resources->counters); 2778 + err_cnt: 2779 + kfree(resources); 2780 + err_res: 2781 + return NULL; 2763 2782 } 2764 2783 2765 2784 void ib_uverbs_flow_resources_free(struct ib_uflow_resources *uflow_res) 2766 2785 { 2767 2786 unsigned int i; 2768 2787 2769 - for (i = 0; i < uflow_res->num; i++) 2788 + for (i = 0; i < uflow_res->collection_num; i++) 2770 2789 atomic_dec(&uflow_res->collection[i]->usecnt); 2771 2790 2791 + for (i = 0; i < uflow_res->counters_num; i++) 2792 + atomic_dec(&uflow_res->counters[i]->usecnt); 2793 + 2794 + kfree(uflow_res->collection); 2795 + kfree(uflow_res->counters); 2772 2796 kfree(uflow_res); 2773 2797 } 2774 2798 2775 2799 static void flow_resources_add(struct ib_uflow_resources *uflow_res, 2776 - struct ib_flow_action *action) 2800 + enum ib_flow_spec_type type, 2801 + void *ibobj) 2777 2802 { 2778 2803 WARN_ON(uflow_res->num >= uflow_res->max); 2779 2804 2780 - atomic_inc(&action->usecnt); 2781 - uflow_res->collection[uflow_res->num++] = action; 2805 + switch (type) { 2806 + case IB_FLOW_SPEC_ACTION_HANDLE: 2807 + atomic_inc(&((struct ib_flow_action *)ibobj)->usecnt); 2808 + uflow_res->collection[uflow_res->collection_num++] = 2809 + (struct ib_flow_action *)ibobj; 2810 + break; 2811 + case IB_FLOW_SPEC_ACTION_COUNT: 2812 + atomic_inc(&((struct ib_counters *)ibobj)->usecnt); 2813 + uflow_res->counters[uflow_res->counters_num++] = 2814 + (struct ib_counters *)ibobj; 2815 + break; 2816 + default: 2817 + WARN_ON(1); 2818 + } 2819 + 2820 + uflow_res->num++; 2782 2821 } 2783 2822 2784 2823 static int kern_spec_to_ib_spec_action(struct ib_ucontext *ucontext, ··· 2854 2815 return -EINVAL; 2855 2816 ib_spec->action.size = 2856 2817 sizeof(struct ib_flow_spec_action_handle); 2857 - flow_resources_add(uflow_res, ib_spec->action.act); 2818 + flow_resources_add(uflow_res, 2819 + IB_FLOW_SPEC_ACTION_HANDLE, 2820 + ib_spec->action.act); 2858 2821 uobj_put_obj_read(ib_spec->action.act); 2822 + break; 2823 + case IB_FLOW_SPEC_ACTION_COUNT: 2824 + if (kern_spec->flow_count.size != 2825 + sizeof(struct ib_uverbs_flow_spec_action_count)) 2826 + return -EINVAL; 2827 + ib_spec->flow_count.counters = 2828 + uobj_get_obj_read(counters, 2829 + UVERBS_OBJECT_COUNTERS, 2830 + kern_spec->flow_count.handle, 2831 + ucontext); 2832 + if (!ib_spec->flow_count.counters) 2833 + return -EINVAL; 2834 + ib_spec->flow_count.size = 2835 + sizeof(struct ib_flow_spec_action_count); 2836 + flow_resources_add(uflow_res, 2837 + IB_FLOW_SPEC_ACTION_COUNT, 2838 + ib_spec->flow_count.counters); 2839 + uobj_put_obj_read(ib_spec->flow_count.counters); 2859 2840 break; 2860 2841 default: 2861 2842 return -EINVAL;
+13
include/uapi/rdma/ib_user_verbs.h
··· 998 998 __u32 reserved1; 999 999 }; 1000 1000 1001 + struct ib_uverbs_flow_spec_action_count { 1002 + union { 1003 + struct ib_uverbs_flow_spec_hdr hdr; 1004 + struct { 1005 + __u32 type; 1006 + __u16 size; 1007 + __u16 reserved; 1008 + }; 1009 + }; 1010 + __u32 handle; 1011 + __u32 reserved1; 1012 + }; 1013 + 1001 1014 struct ib_uverbs_flow_tunnel_filter { 1002 1015 __be32 tunnel_id; 1003 1016 };