Re: [PATCH rdma-next 05/15] IB/uverbs: Add flow_action create and destroy verbs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 21/03/2018 16:57, Jason Gunthorpe wrote:
On Wed, Mar 21, 2018 at 04:38:45PM +0200, Matan Barak wrote:
On 21/03/2018 03:44, Jason Gunthorpe wrote:
On Tue, Mar 20, 2018 at 03:01:36PM +0200, Leon Romanovsky wrote:

+struct ib_uverbs_flow_action_esp_encap {
+	/* This struct represents a list of pointers to flow_xxxx_filter that
+	 * encapsulates the payload in ESP tunnel mode.
+	 */
+	RDMA_UAPI_PTR(void *, val_ptr); /* pointer to a flow_xxxx_filter */
+	RDMA_UAPI_PTR(struct ib_uverbs_flow_action_esp_encap *, next_ptr);
+	__u16	len;		/* Len of the filter struct val_ptr points to */
+	__u16	type;		/* Use flow_spec_type enum */
+};

Did you test this Matan? It doesn't work the way you think:

#include <linux/types.h>
#include <assert.h>

#define RDMA_UAPI_PTR(_type, _name)     _type __attribute__((aligned(8))) _name

struct ib_uverbs_flow_action_esp_encap {
	/* This struct represents a list of pointers to flow_xxxx_filter that
	 * encapsulates the payload in ESP tunnel mode.
	 */
	RDMA_UAPI_PTR(void *, val_ptr); /* pointer to a flow_xxxx_filter */
	RDMA_UAPI_PTR(struct ib_uverbs_flow_action_esp_encap *, next_ptr);
	__u16	len;		/* Len of the filter struct val_ptr points to */
	__u16	type;		/* Use flow_spec_type enum */
};

static_assert(sizeof(struct ib_uverbs_flow_action_esp_encap) == 8*3, "Bad size");
static_assert(__alignof__(struct ib_uverbs_flow_action_esp_encap) == 8, "Bad Align");

$ gcc -std=c11 -Wall -c /tmp/t.c -m32
In file included from /tmp/t.c:2:0:
/tmp/t.c:16:1: error: static assertion failed: "Bad size"
  static_assert(sizeof(struct ib_uverbs_flow_action_esp_encap) == 8*3, "Bad size");

$ pahole32 t.o
struct ib_uverbs_flow_action_esp_encap {
	void *                     val_ptr;              /*     0     4 */

	/* XXX 4 bytes hole, try to pack */

	struct ib_uverbs_flow_action_esp_encap * next_ptr; /*     8     4 */
	__u16                      len;                  /*    12     2 */
	__u16                      type;                 /*    14     2 */

	/* size: 16, cachelines: 1, members: 4 */
	/* sum members: 12, holes: 1, sum holes: 4 */
	/* last cacheline: 16 bytes */
};

And why is a pointer in a user struct?

The kernel default for RDMA_UAPI_PTR() should simply be

  #define RDMA_UAPI_PTR(_type, _name) __aligned_u64 _name

Because we always have to use u64_to_user_ptr() anyhow.

Userspace needs to redefine it to

  #define RDMA_UAPI_PTR(_type, _name) union {_type _name; __aligned_u64 _dummy_#_name;}
or
  #define RDMA_UAPI_PTR(_type, _name) union {struct {__u32  _dummy2_##_name; _type _name; __aligned_u64 _dummy_##_name;}

Depending on endian


This is redefined in the user-space code at libibverbs/verbs_api.h by:
#if UINTPTR_MAX == UINT32_MAX
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define RDMA_UAPI_PTR(_type, _name) union {                            \
                                        struct {_type _name;            \
                                                __u32 _name ##_reserved;\
                                        };                              \
                                        __u64 _name ## _data_u64; }     \
                                        __attribute__((aligned(8)))
#else
#define RDMA_UAPI_PTR(_type, _name) union {                            \
                                        struct {__u32 _name ##_reserved;\
                                                _type _name;            \
                                        };                              \
                                        __u64 _name ## _data_u64; }     \
                                        __attribute__((aligned(8)))

Should be __aligned_u64, but yes, that is fine.

The 64 bit version should be

union {_type _name; __aligned_u64 _name ## _data_u64; }

Though, just to make sure the alignment is right.

So only the kernel macro is wrong, please fix it to

  #define RDMA_UAPI_PTR(_type, _name) __aligned_u64 _name


By doing this, you're loosing the type information.
Why not defining it both in user-space and kernel as
union {_type _name; __aligned_u64 _name ## _data_u64; }

Jason


Matan
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux