Skip to content

Commit

Permalink
Merge branch 'bpf-af-xdp-cleanups'
Browse files Browse the repository at this point in the history
Björn Töpel says:

====================
This the second follow-up set. The first four patches are uapi
changes:

* Removing rebind support
* Getting rid of structure hole
* Removing explicit cache line alignment
* Stricter bind checks

The last patches do some cleanups, where the umem and refcount_t
changes were suggested by Daniel.

* Add a missing write-barrier and use READ_ONCE for data-dependencies
* Clean up umem and do proper locking
* Convert atomic_t to refcount_t
====================

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
  • Loading branch information
Daniel Borkmann committed May 22, 2018
2 parents d849f9f + d3b42f1 commit fd0bfa8
Show file tree
Hide file tree
Showing 6 changed files with 225 additions and 156 deletions.
46 changes: 23 additions & 23 deletions include/uapi/linux/if_xdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,33 @@

struct sockaddr_xdp {
__u16 sxdp_family;
__u16 sxdp_flags;
__u32 sxdp_ifindex;
__u32 sxdp_queue_id;
__u32 sxdp_shared_umem_fd;
__u16 sxdp_flags;
};

struct xdp_ring_offset {
__u64 producer;
__u64 consumer;
__u64 desc;
};

struct xdp_mmap_offsets {
struct xdp_ring_offset rx;
struct xdp_ring_offset tx;
struct xdp_ring_offset fr; /* Fill */
struct xdp_ring_offset cr; /* Completion */
};

/* XDP socket options */
#define XDP_RX_RING 1
#define XDP_TX_RING 2
#define XDP_UMEM_REG 3
#define XDP_UMEM_FILL_RING 4
#define XDP_UMEM_COMPLETION_RING 5
#define XDP_STATISTICS 6
#define XDP_MMAP_OFFSETS 1
#define XDP_RX_RING 2
#define XDP_TX_RING 3
#define XDP_UMEM_REG 4
#define XDP_UMEM_FILL_RING 5
#define XDP_UMEM_COMPLETION_RING 6
#define XDP_STATISTICS 7

struct xdp_umem_reg {
__u64 addr; /* Start of packet data area */
Expand All @@ -50,6 +64,7 @@ struct xdp_statistics {
#define XDP_UMEM_PGOFF_FILL_RING 0x100000000
#define XDP_UMEM_PGOFF_COMPLETION_RING 0x180000000

/* Rx/Tx descriptor */
struct xdp_desc {
__u32 idx;
__u32 len;
Expand All @@ -58,21 +73,6 @@ struct xdp_desc {
__u8 padding[5];
};

struct xdp_ring {
__u32 producer __attribute__((aligned(64)));
__u32 consumer __attribute__((aligned(64)));
};

/* Used for the RX and TX queues for packets */
struct xdp_rxtx_ring {
struct xdp_ring ptrs;
struct xdp_desc desc[0] __attribute__((aligned(64)));
};

/* Used for the fill and completion queues for buffers */
struct xdp_umem_ring {
struct xdp_ring ptrs;
__u32 desc[0] __attribute__((aligned(64)));
};
/* UMEM descriptor is __u32 */

#endif /* _LINUX_IF_XDP_H */
85 changes: 41 additions & 44 deletions net/xdp/xdp_umem.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,25 @@

#define XDP_UMEM_MIN_FRAME_SIZE 2048

int xdp_umem_create(struct xdp_umem **umem)
{
*umem = kzalloc(sizeof(**umem), GFP_KERNEL);

if (!*umem)
return -ENOMEM;

return 0;
}

static void xdp_umem_unpin_pages(struct xdp_umem *umem)
{
unsigned int i;

if (umem->pgs) {
for (i = 0; i < umem->npgs; i++) {
struct page *page = umem->pgs[i];

set_page_dirty_lock(page);
put_page(page);
}
for (i = 0; i < umem->npgs; i++) {
struct page *page = umem->pgs[i];

kfree(umem->pgs);
umem->pgs = NULL;
set_page_dirty_lock(page);
put_page(page);
}

kfree(umem->pgs);
umem->pgs = NULL;
}

static void xdp_umem_unaccount_pages(struct xdp_umem *umem)
{
if (umem->user) {
atomic_long_sub(umem->npgs, &umem->user->locked_vm);
free_uid(umem->user);
}
atomic_long_sub(umem->npgs, &umem->user->locked_vm);
free_uid(umem->user);
}

static void xdp_umem_release(struct xdp_umem *umem)
Expand All @@ -66,22 +52,18 @@ static void xdp_umem_release(struct xdp_umem *umem)
umem->cq = NULL;
}

if (umem->pgs) {
xdp_umem_unpin_pages(umem);

task = get_pid_task(umem->pid, PIDTYPE_PID);
put_pid(umem->pid);
if (!task)
goto out;
mm = get_task_mm(task);
put_task_struct(task);
if (!mm)
goto out;
xdp_umem_unpin_pages(umem);

mmput(mm);
umem->pgs = NULL;
}
task = get_pid_task(umem->pid, PIDTYPE_PID);
put_pid(umem->pid);
if (!task)
goto out;
mm = get_task_mm(task);
put_task_struct(task);
if (!mm)
goto out;

mmput(mm);
xdp_umem_unaccount_pages(umem);
out:
kfree(umem);
Expand All @@ -96,15 +78,15 @@ static void xdp_umem_release_deferred(struct work_struct *work)

void xdp_get_umem(struct xdp_umem *umem)
{
atomic_inc(&umem->users);
refcount_inc(&umem->users);
}

void xdp_put_umem(struct xdp_umem *umem)
{
if (!umem)
return;

if (atomic_dec_and_test(&umem->users)) {
if (refcount_dec_and_test(&umem->users)) {
INIT_WORK(&umem->work, xdp_umem_release_deferred);
schedule_work(&umem->work);
}
Expand Down Expand Up @@ -167,16 +149,13 @@ static int xdp_umem_account_pages(struct xdp_umem *umem)
return 0;
}

int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
{
u32 frame_size = mr->frame_size, frame_headroom = mr->frame_headroom;
u64 addr = mr->addr, size = mr->len;
unsigned int nframes, nfpp;
int size_chk, err;

if (!umem)
return -EINVAL;

if (frame_size < XDP_UMEM_MIN_FRAME_SIZE || frame_size > PAGE_SIZE) {
/* Strictly speaking we could support this, if:
* - huge pages, or*
Expand Down Expand Up @@ -227,7 +206,7 @@ int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
umem->frame_size_log2 = ilog2(frame_size);
umem->nfpp_mask = nfpp - 1;
umem->nfpplog2 = ilog2(nfpp);
atomic_set(&umem->users, 1);
refcount_set(&umem->users, 1);

err = xdp_umem_account_pages(umem);
if (err)
Expand All @@ -245,6 +224,24 @@ int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
return err;
}

struct xdp_umem *xdp_umem_create(struct xdp_umem_reg *mr)
{
struct xdp_umem *umem;
int err;

umem = kzalloc(sizeof(*umem), GFP_KERNEL);
if (!umem)
return ERR_PTR(-ENOMEM);

err = xdp_umem_reg(umem, mr);
if (err) {
kfree(umem);
return ERR_PTR(err);
}

return umem;
}

bool xdp_umem_validate_queues(struct xdp_umem *umem)
{
return umem->fq && umem->cq;
Expand Down
5 changes: 2 additions & 3 deletions net/xdp/xdp_umem.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ struct xdp_umem {
struct pid *pid;
unsigned long address;
size_t size;
atomic_t users;
refcount_t users;
struct work_struct work;
};

Expand All @@ -50,9 +50,8 @@ static inline char *xdp_umem_get_data_with_headroom(struct xdp_umem *umem,
}

bool xdp_umem_validate_queues(struct xdp_umem *umem);
int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr);
void xdp_get_umem(struct xdp_umem *umem);
void xdp_put_umem(struct xdp_umem *umem);
int xdp_umem_create(struct xdp_umem **umem);
struct xdp_umem *xdp_umem_create(struct xdp_umem_reg *mr);

#endif /* XDP_UMEM_H_ */
Loading

0 comments on commit fd0bfa8

Please sign in to comment.