Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Xsk migration with multiprog support #92

Closed
wants to merge 3 commits into from
Closed

Conversation

magnus-karlsson
Copy link
Member

Pushed a whole new branch. Rewrote the handling of loading and manipulating the default xsk program using your xdp_program__* APIs and fixed all your other comments. Also updated with the latest changes from the Linux repo version.

Make the print functions in libxdp.c visible to other files by putting
them in a new header file called libxdp_internal.h. These print
functions can then be used by the new AF_XDP support that will be
added in the next commit.

Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
Add AF_XDP functionality to libxdp. This is the same functionality as
in libbpf in the kernel tree at the moment. The plan is to remove this
from libbpf before the 1.0 release and for libxdp to be its new home.

Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
Add documentation for the AF_XDP socket support in libxdp.

Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
@tohojo tohojo mentioned this pull request Feb 15, 2021
Copy link
Member

@tohojo tohojo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments; biggest issue is probably the race condition / locking thing.

Also, did you have a chance to test if using the XDP dispatcher has any measurable performance overhead? :)

PC_FILE := $(OBJDIR)/libxdp.pc
TEMPLATED_SOURCES := xdp-dispatcher.c

CFLAGS += -I$(HEADER_DIR) -I$(LIB_DIR)/util
CFLAGS += -I$(HEADER_DIR) -I$(LIB_DIR)/util -O0 -g
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not ;-). Just garbage left after a debug session.

int ifindex;
struct list_head list;
struct xdp_program *xdp_prog;
int prog_fd;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why have both? It's possible to build an xdp_program from an fd (xdp_program__from_fd()), so just keeping the xdp_prog pointer saves branching (see comments below).

close(ctx->xsks_map_fd);
}

static int xsk_lookup_bpf_map(struct xsk_socket *xsk)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this function I wonder if it would make sense to have libxdp parse the list of maps in xdp_program__fill_from_fd() so they are always available to callers? A bit orthogonal to this patch, but may be generally useful? WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might make sense, but if this is never performance critical it might not make sense to waste the memory. In my case, performance is not an issue.

continue;
}

if (!strcmp(map_info.name, "xsks_map")) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a little worried about forward compatibility here; what if we need to change the layout of xsks_map in the future? I think we should at least checking that the key and value size matches what we expect...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Will fix.


if (!prog)
return -1;
return xdp_program__fd(prog);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This leaks the multi_prog reference... Given what I said above re: just keeping the xdp_program reference, maybe the right thing here is to have this function return an xdp_program pointer, and expose xdp_program__clone() so it can still close the multiprog...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will make a stab at just using the program pointer and make sure to destroy it when necessary.

xdp_program__detach(ctx->xdp_prog, ctx->ifindex,
xsk_convert_xdp_flags(xsk->config.xdp_flags), 0);
err_prog_load:
xdp_program__close(ctx->xdp_prog);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should clear the pointer as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix.


ctx->prog_fd = -1;

if (!(xsk->config.libbpf_flags & XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This flag is not mentioned in the documentation :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops! Will add.

if (ctx->xdp_prog)
xdp_program__close(ctx->xdp_prog);
else
close(ctx->prog_fd);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we just always store ctx->xdp_prog this disambiguation is not needed anymore...

return -1;

while ((prog = xdp_multiprog__next_prog(prog, multi_prog)))
if (!strcmp(xdp_program__name(prog), "xsk_def_prog"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also a potential forward-compatibility concern. If we ever need to change the default program in an incompatible way, we'd get subtle breakage when mixing library versions. I put a version check into the dispatcher program for just this reason - see check_dispatcher_version(), and feel free to just copy that (or better, refactor it to be reusable for this :))

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Will steal your code ;-).

return xsk_add_map_entry(xsk);
}

int xsk_setup_xdp_prog(int ifindex, int *xsks_map_fd)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is the application supposed to tear down the XDP prog again? Or rather, how is an application supposed to do this without racing against another program trying to install itself? Since we abstract away the creation and attachment of the XDP program, I think we need to handle the race condition as well...

We do already have a locking mechanism (in xdp_lock_acquire/release()) we could use, but a bit of care is needed to prevent deadlocking with outselves (xdp_program__attach() will grab the lock). So may need a bit more knowledge of the internals of the rest of the library... WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have kept all locking outside the library by design. I think this is best left up to the user to fix with a synchronization primitive of its choosing which might even be none with certain designs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For synchronisation inside an application I agree that we shouldn't impose any particular locking. But this also has to do with synchronisation between applications, that don't necessarily have any way of coordinating, other than libxdp. So I think solving this in a race-free way is in scope; it's basically the same issue as Maciej's patch[0] is addressing in the libbpf version of this code.

[0] https://lore.kernel.org/bpf/3a625c8b-6dc0-3933-25e5-f747197ae1f4@intel.com/T/#t

@magnus-karlsson
Copy link
Member Author

A few comments; biggest issue is probably the race condition / locking thing.

I think we should not implement any locking as discussed above. Let the user do this if it needs it.

Also, did you have a chance to test if using the XDP dispatcher has any measurable performance overhead? :)

No, I have not done this yet. I take an action to do it.

@magnus-karlsson
Copy link
Member Author

magnus-karlsson commented Feb 16, 2021 via email

@tohojo
Copy link
Member

tohojo commented Feb 16, 2021 via email

@magnus-karlsson
Copy link
Member Author

Pushed a new version/branch

@tohojo
Copy link
Member

tohojo commented Mar 23, 2021 via email

@magnus-karlsson
Copy link
Member Author

magnus-karlsson commented Mar 23, 2021 via email

@tohojo tohojo deleted the xsk_migration3 branch February 18, 2022 13:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants