Re: [PATCH bpf-next 1/2] libbpf: add support for using AF_XDP sockets
From: Daniel Borkmann <daniel@iogearbox.net>
Date: 2018-12-12 01:14:26
On 12/10/2018 04:34 PM, Magnus Karlsson wrote: [...]
+int xsk_create_umem(void *umem_area, __u64 size, struct xsk_prod_ring *fq,
+ struct xsk_cons_ring *cq,
+ struct xsk_umem_config *usr_config)
+{
+ struct xdp_mmap_offsets off;
+ struct xsk_umem_info *umem;
+ struct xdp_umem_reg mr;
+ socklen_t optlen;
+ int err, fd;
+ void *map;
+
+ if (!umem_area)
+ return -EFAULT;
+ if (!size && !xsk_page_aligned(umem_area))
+ return -EINVAL;
+
+ fd = socket(AF_XDP, SOCK_RAW, 0);
+ if (fd < 0)
+ return -errno;
+
+ umem = calloc(1, sizeof(*umem));
+ if (!umem)
+ return -ENOMEM;On error, we should also close fd and not 'leak' it into the app, similar for other errors below. Same in xsk_create_xdp_socket(), etc.
+ xsk_hash_insert_umem(fd, umem); + xsk_set_umem_config(&umem->config, usr_config); + + mr.addr = (uintptr_t)umem_area; + mr.len = size; + mr.chunk_size = umem->config.frame_size; + mr.headroom = umem->config.frame_headroom; + + err = setsockopt(fd, SOL_XDP, XDP_UMEM_REG, &mr, sizeof(mr)); + if (err) + return -errno; + err = setsockopt(fd, SOL_XDP, XDP_UMEM_FILL_RING, + &umem->config.fq_size, sizeof(umem->config.fq_size)); + if (err) + return -errno; + err = setsockopt(fd, SOL_XDP, XDP_UMEM_COMPLETION_RING, + &umem->config.cq_size, sizeof(umem->config.cq_size)); + if (err) + return -errno; + + optlen = sizeof(off); + err = getsockopt(fd, SOL_XDP, XDP_MMAP_OFFSETS, &off, &optlen); + if (err) + return -errno; + + map = xsk_mmap(NULL, off.fr.desc + umem->config.fq_size * sizeof(__u64), + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, + fd, XDP_UMEM_PGOFF_FILL_RING); + if (map == MAP_FAILED) + return -errno; + + umem->fq = fq; + fq->mask = umem->config.fq_size - 1; + fq->size = umem->config.fq_size; + fq->producer = map + off.fr.producer; + fq->consumer = map + off.fr.consumer; + fq->ring = map + off.fr.desc; + fq->cached_cons = umem->config.fq_size; + + map = xsk_mmap(NULL, off.cr.desc + umem->config.cq_size * sizeof(__u64), + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, + fd, XDP_UMEM_PGOFF_COMPLETION_RING); + if (map == MAP_FAILED) + return -errno;
Plus undoing prior mmaps.
+ umem->cq = cq; + cq->mask = umem->config.cq_size - 1; + cq->size = umem->config.cq_size; + cq->producer = map + off.cr.producer; + cq->consumer = map + off.cr.consumer; + cq->ring = map + off.cr.desc; + + umem->umem_area = umem_area; + umem->fd = fd; + + return fd; +}
Thanks, Daniel