From: Stanislav Fomichev <stfomichev@gmail.com>
To: Mina Almasry <almasrymina@google.com>
Cc: Stanislav Fomichev <sdf@fomichev.me>,
netdev@vger.kernel.org, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com
Subject: Re: [PATCH net-next v2 02/12] selftests: ncdevmem: Separate out dmabuf provider
Date: Thu, 3 Oct 2024 15:08:04 -0700 [thread overview]
Message-ID: <Zv8VxOJiEWHmcWpj@mini-arch> (raw)
In-Reply-To: <CAHS8izNGphJPD6-PkATnOETj-LFLadSAKTe_A+FiJ_3Cax35ZA@mail.gmail.com>
On 10/03, Mina Almasry wrote:
> On Mon, Sep 30, 2024 at 10:18 AM Stanislav Fomichev <sdf@fomichev.me> wrote:
> >
> > So we can plug the other ones in the future if needed.
> >
> > Cc: Mina Almasry <almasrymina@google.com>
> > Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
>
> Feedback is minor, so with or without it:
>
> Reviewed-by: Mina Almasry <almasrymina@google.com>
>
> > ---
> > tools/testing/selftests/net/ncdevmem.c | 215 +++++++++++++++----------
> > 1 file changed, 134 insertions(+), 81 deletions(-)
> >
> > diff --git a/tools/testing/selftests/net/ncdevmem.c b/tools/testing/selftests/net/ncdevmem.c
> > index 9245d3f158dd..557175c3bf02 100644
> > --- a/tools/testing/selftests/net/ncdevmem.c
> > +++ b/tools/testing/selftests/net/ncdevmem.c
> > @@ -71,17 +71,118 @@ static char *ifname = "eth1";
> > static unsigned int ifindex;
> > static unsigned int dmabuf_id;
> >
> > -void print_bytes(void *ptr, size_t size)
> > +struct memory_buffer {
> > + int fd;
> > + size_t size;
> > +
> > + int devfd;
> > + int memfd;
> > + char *buf_mem;
> > +};
> > +
> > +struct memory_provider {
> > + struct memory_buffer *(*alloc)(size_t size);
> > + void (*free)(struct memory_buffer *ctx);
> > + void (*memcpy_to_device)(struct memory_buffer *dst, size_t off,
> > + void *src, int n);
>
> AFAICT all this code in this api and its implementation is unused. I'm
> guessing this is for the future TX path testing?
>
> If you get the chance to slice these changes out of this patch and
> punting them for when the TX changes are ready, please do. Just to
> minimize dead code until TX path is added, but since these are tests,
> dead code is not a huge deal.
Ah, yes, I'll remove it for now.
> > + void (*memcpy_from_device)(void *dst, struct memory_buffer *src,
> > + size_t off, int n);
> > +};
> > +
> > +static struct memory_buffer *udmabuf_alloc(size_t size)
> > {
> > - unsigned char *p = ptr;
> > - int i;
> > + struct udmabuf_create create;
> > + struct memory_buffer *ctx;
> > + int ret;
> >
> > - for (i = 0; i < size; i++)
> > - printf("%02hhX ", p[i]);
> > - printf("\n");
> > + ctx = malloc(sizeof(*ctx));
> > + if (!ctx)
> > + error(1, ENOMEM, "malloc failed");
> > +
> > + ctx->size = size;
> > +
> > + ctx->devfd = open("/dev/udmabuf", O_RDWR);
> > + if (ctx->devfd < 0)
> > + error(1, errno,
> > + "%s: [skip,no-udmabuf: Unable to access DMA buffer device file]\n",
> > + TEST_PREFIX);
> > +
> > + ctx->memfd = memfd_create("udmabuf-test", MFD_ALLOW_SEALING);
> > + if (ctx->memfd < 0)
> > + error(1, errno, "%s: [skip,no-memfd]\n", TEST_PREFIX);
> > +
> > + ret = fcntl(ctx->memfd, F_ADD_SEALS, F_SEAL_SHRINK);
> > + if (ret < 0)
> > + error(1, errno, "%s: [skip,fcntl-add-seals]\n", TEST_PREFIX);
> > +
> > + ret = ftruncate(ctx->memfd, size);
> > + if (ret == -1)
> > + error(1, errno, "%s: [FAIL,memfd-truncate]\n", TEST_PREFIX);
> > +
> > + memset(&create, 0, sizeof(create));
> > +
> > + create.memfd = ctx->memfd;
> > + create.offset = 0;
> > + create.size = size;
> > + ctx->fd = ioctl(ctx->devfd, UDMABUF_CREATE, &create);
> > + if (ctx->fd < 0)
> > + error(1, errno, "%s: [FAIL, create udmabuf]\n", TEST_PREFIX);
> > +
> > + ctx->buf_mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
> > + ctx->fd, 0);
> > + if (ctx->buf_mem == MAP_FAILED)
> > + error(1, errno, "%s: [FAIL, map udmabuf]\n", TEST_PREFIX);
> > +
> > + return ctx;
> > +}
> > +
> > +static void udmabuf_free(struct memory_buffer *ctx)
> > +{
> > + munmap(ctx->buf_mem, ctx->size);
> > + close(ctx->fd);
> > + close(ctx->memfd);
> > + close(ctx->devfd);
> > + free(ctx);
> > +}
> > +
> > +static void udmabuf_memcpy_to_device(struct memory_buffer *dst, size_t off,
> > + void *src, int n)
> > +{
> > + struct dma_buf_sync sync = {};
> > +
> > + sync.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_WRITE;
> > + ioctl(dst->fd, DMA_BUF_IOCTL_SYNC, &sync);
> > +
> > + memcpy(dst->buf_mem + off, src, n);
> > +
> > + sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_WRITE;
> > + ioctl(dst->fd, DMA_BUF_IOCTL_SYNC, &sync);
> > +}
> > +
> > +static void udmabuf_memcpy_from_device(void *dst, struct memory_buffer *src,
> > + size_t off, int n)
> > +{
> > + struct dma_buf_sync sync = {};
> > +
> > + sync.flags = DMA_BUF_SYNC_START;
> > + ioctl(src->fd, DMA_BUF_IOCTL_SYNC, &sync);
> > +
> > + memcpy(dst, src->buf_mem + off, n);
> > +
> > + sync.flags = DMA_BUF_SYNC_END;
> > + ioctl(src->fd, DMA_BUF_IOCTL_SYNC, &sync);
> > }
> >
> > -void print_nonzero_bytes(void *ptr, size_t size)
> > +static struct memory_provider udmabuf_memory_provider = {
> > + .alloc = udmabuf_alloc,
> > + .free = udmabuf_free,
> > + .memcpy_to_device = udmabuf_memcpy_to_device,
> > + .memcpy_from_device = udmabuf_memcpy_from_device,
> > +};
> > +
> > +static struct memory_provider *provider = &udmabuf_memory_provider;
> > +
> > +static void print_nonzero_bytes(void *ptr, size_t size)
> > {
> > unsigned char *p = ptr;
> > unsigned int i;
> > @@ -201,42 +302,7 @@ static int bind_rx_queue(unsigned int ifindex, unsigned int dmabuf_fd,
> > return -1;
> > }
> >
> > -static void create_udmabuf(int *devfd, int *memfd, int *buf, size_t dmabuf_size)
> > -{
> > - struct udmabuf_create create;
> > - int ret;
> > -
> > - *devfd = open("/dev/udmabuf", O_RDWR);
> > - if (*devfd < 0) {
> > - error(70, 0,
> > - "%s: [skip,no-udmabuf: Unable to access DMA buffer device file]\n",
> > - TEST_PREFIX);
> > - }
> > -
> > - *memfd = memfd_create("udmabuf-test", MFD_ALLOW_SEALING);
> > - if (*memfd < 0)
> > - error(70, 0, "%s: [skip,no-memfd]\n", TEST_PREFIX);
> > -
> > - /* Required for udmabuf */
> > - ret = fcntl(*memfd, F_ADD_SEALS, F_SEAL_SHRINK);
> > - if (ret < 0)
> > - error(73, 0, "%s: [skip,fcntl-add-seals]\n", TEST_PREFIX);
> > -
> > - ret = ftruncate(*memfd, dmabuf_size);
> > - if (ret == -1)
> > - error(74, 0, "%s: [FAIL,memfd-truncate]\n", TEST_PREFIX);
> > -
> > - memset(&create, 0, sizeof(create));
> > -
> > - create.memfd = *memfd;
> > - create.offset = 0;
> > - create.size = dmabuf_size;
> > - *buf = ioctl(*devfd, UDMABUF_CREATE, &create);
> > - if (*buf < 0)
> > - error(75, 0, "%s: [FAIL, create udmabuf]\n", TEST_PREFIX);
> > -}
> > -
> > -int do_server(void)
> > +int do_server(struct memory_buffer *mem)
> > {
> > char ctrl_data[sizeof(int) * 20000];
> > struct netdev_queue_id *queues;
> > @@ -244,23 +310,18 @@ int do_server(void)
> > struct sockaddr_in client_addr;
> > struct sockaddr_in server_sin;
> > size_t page_aligned_frags = 0;
> > - int devfd, memfd, buf, ret;
> > size_t total_received = 0;
> > socklen_t client_addr_len;
> > bool is_devmem = false;
> > - char *buf_mem = NULL;
> > + char *tmp_mem = NULL;
> > struct ynl_sock *ys;
> > - size_t dmabuf_size;
> > char iobuf[819200];
> > char buffer[256];
> > int socket_fd;
> > int client_fd;
> > size_t i = 0;
> > int opt = 1;
> > -
> > - dmabuf_size = getpagesize() * NUM_PAGES;
> > -
> > - create_udmabuf(&devfd, &memfd, &buf, dmabuf_size);
> > + int ret;
> >
> > if (reset_flow_steering())
> > error(1, 0, "Failed to reset flow steering\n");
> > @@ -284,13 +345,12 @@ int do_server(void)
> > queues[i].id = start_queue + i;
> > }
> >
> > - if (bind_rx_queue(ifindex, buf, queues, num_queues, &ys))
> > + if (bind_rx_queue(ifindex, mem->fd, queues, num_queues, &ys))
> > error(1, 0, "Failed to bind\n");
> >
> > - buf_mem = mmap(NULL, dmabuf_size, PROT_READ | PROT_WRITE, MAP_SHARED,
> > - buf, 0);
> > - if (buf_mem == MAP_FAILED)
> > - error(1, 0, "mmap()");
> > + tmp_mem = malloc(mem->size);
> > + if (!tmp_mem)
> > + error(1, ENOMEM, "malloc failed");
> >
> > server_sin.sin_family = AF_INET;
> > server_sin.sin_port = htons(atoi(port));
> > @@ -341,7 +401,6 @@ int do_server(void)
> > struct iovec iov = { .iov_base = iobuf,
> > .iov_len = sizeof(iobuf) };
> > struct dmabuf_cmsg *dmabuf_cmsg = NULL;
> > - struct dma_buf_sync sync = { 0 };
> > struct cmsghdr *cm = NULL;
> > struct msghdr msg = { 0 };
> > struct dmabuf_token token;
> > @@ -410,22 +469,17 @@ int do_server(void)
> > else
> > page_aligned_frags++;
> >
> > - sync.flags = DMA_BUF_SYNC_READ | DMA_BUF_SYNC_START;
> > - ioctl(buf, DMA_BUF_IOCTL_SYNC, &sync);
> > + provider->memcpy_from_device(tmp_mem, mem,
> > + dmabuf_cmsg->frag_offset,
> > + dmabuf_cmsg->frag_size);
> >
> > if (do_validation)
> > validate_buffer(
> > - ((unsigned char *)buf_mem) +
> > + ((unsigned char *)tmp_mem) +
> > dmabuf_cmsg->frag_offset,
> > dmabuf_cmsg->frag_size);
> > else
> > - print_nonzero_bytes(
> > - ((unsigned char *)buf_mem) +
> > - dmabuf_cmsg->frag_offset,
> > - dmabuf_cmsg->frag_size);
> > -
> > - sync.flags = DMA_BUF_SYNC_READ | DMA_BUF_SYNC_END;
> > - ioctl(buf, DMA_BUF_IOCTL_SYNC, &sync);
> > + print_nonzero_bytes(tmp_mem, dmabuf_cmsg->frag_size);
> >
> > ret = setsockopt(client_fd, SOL_SOCKET,
> > SO_DEVMEM_DONTNEED, &token,
> > @@ -450,12 +504,9 @@ int do_server(void)
> >
> > cleanup:
> >
> > - munmap(buf_mem, dmabuf_size);
> > + free(tmp_mem);
> > close(client_fd);
> > close(socket_fd);
> > - close(buf);
> > - close(memfd);
> > - close(devfd);
> > ynl_sock_destroy(ys);
> >
> > return 0;
> > @@ -464,14 +515,11 @@ int do_server(void)
> > void run_devmem_tests(void)
> > {
> > struct netdev_queue_id *queues;
> > - int devfd, memfd, buf;
> > + struct memory_buffer *mem;
> > struct ynl_sock *ys;
> > - size_t dmabuf_size;
> > size_t i = 0;
> >
> > - dmabuf_size = getpagesize() * NUM_PAGES;
> > -
> > - create_udmabuf(&devfd, &memfd, &buf, dmabuf_size);
> > + mem = provider->alloc(getpagesize() * NUM_PAGES);
> >
>
> There is some weirdness here where run_devmem_tests() allocates its
> own provider, but do_server() uses a provider allocated in main(). Any
> reason these are not symmetric? I would marginally prefer do_server()
> to allocate its own provider just like run_devmem_tests(), or at least
> make them both match, if possible.
I wanted to keep them separate in case we end up adding more to
the selftest part. For example, not sure what would happen now if we pass
a udmabuf with just one page? Do we need some test for the drivers
to make sure they handle this case?
next prev parent reply other threads:[~2024-10-03 22:08 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-09-30 17:17 [PATCH net-next v2 00/12] selftests: ncdevmem: Add ncdevmem to ksft Stanislav Fomichev
2024-09-30 17:17 ` [PATCH net-next v2 01/12] selftests: ncdevmem: Redirect all non-payload output to stderr Stanislav Fomichev
2024-10-03 17:40 ` Mina Almasry
2024-09-30 17:17 ` [PATCH net-next v2 02/12] selftests: ncdevmem: Separate out dmabuf provider Stanislav Fomichev
2024-10-03 17:57 ` Mina Almasry
2024-10-03 22:08 ` Stanislav Fomichev [this message]
2024-10-04 1:42 ` Mina Almasry
2024-09-30 17:17 ` [PATCH net-next v2 03/12] selftests: ncdevmem: Unify error handling Stanislav Fomichev
2024-10-03 6:57 ` Mina Almasry
2024-09-30 17:17 ` [PATCH net-next v2 04/12] selftests: ncdevmem: Make client_ip optional Stanislav Fomichev
2024-10-03 6:56 ` Mina Almasry
2024-09-30 17:17 ` [PATCH net-next v2 05/12] selftests: ncdevmem: Remove default arguments Stanislav Fomichev
2024-10-03 6:59 ` Mina Almasry
2024-10-03 16:36 ` Stanislav Fomichev
2024-10-03 18:51 ` Mina Almasry
2024-09-30 17:17 ` [PATCH net-next v2 06/12] selftests: ncdevmem: Switch to AF_INET6 Stanislav Fomichev
2024-10-03 7:07 ` Mina Almasry
2024-10-03 16:47 ` Stanislav Fomichev
2024-10-03 17:16 ` Mina Almasry
2024-09-30 17:17 ` [PATCH net-next v2 07/12] selftests: ncdevmem: Properly reset flow steering Stanislav Fomichev
2024-10-03 7:02 ` Mina Almasry
2024-10-03 16:42 ` Stanislav Fomichev
2024-10-03 18:54 ` Mina Almasry
2024-10-03 22:12 ` Stanislav Fomichev
2024-09-30 17:17 ` [PATCH net-next v2 08/12] selftests: ncdevmem: Use YNL to enable TCP header split Stanislav Fomichev
2024-10-03 7:22 ` Mina Almasry
2024-10-03 16:57 ` Stanislav Fomichev
2024-09-30 17:17 ` [PATCH net-next v2 09/12] selftests: ncdevmem: Remove hard-coded queue numbers Stanislav Fomichev
2024-10-03 7:14 ` Mina Almasry
2024-10-03 17:02 ` Stanislav Fomichev
2024-10-03 19:07 ` Mina Almasry
2024-10-03 22:16 ` Stanislav Fomichev
2024-09-30 17:17 ` [PATCH net-next v2 10/12] selftests: ncdevmem: Run selftest when none of the -s or -c has been provided Stanislav Fomichev
2024-10-03 7:26 ` Mina Almasry
2024-10-03 17:18 ` Stanislav Fomichev
2024-10-03 19:10 ` Mina Almasry
2024-09-30 17:17 ` [PATCH net-next v2 11/12] selftests: ncdevmem: Move ncdevmem under drivers/net/hw Stanislav Fomichev
2024-10-03 7:29 ` Mina Almasry
2024-10-03 17:25 ` Stanislav Fomichev
2024-10-03 19:16 ` Mina Almasry
2024-09-30 17:17 ` [PATCH net-next v2 12/12] selftests: ncdevmem: Add automated test Stanislav Fomichev
2024-10-03 7:39 ` Mina Almasry
2024-10-03 17:47 ` Stanislav Fomichev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Zv8VxOJiEWHmcWpj@mini-arch \
--to=stfomichev@gmail.com \
--cc=almasrymina@google.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=sdf@fomichev.me \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.