-
Notifications
You must be signed in to change notification settings - Fork 130
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
Conversation
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>
There was a problem hiding this 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this needed?
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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")) { |
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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)) { |
There was a problem hiding this comment.
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 :)
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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")) |
There was a problem hiding this comment.
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 :))
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
I think we should not implement any locking as discussed above. Let the user do this if it needs it.
No, I have not done this yet. I take an action to do it. |
On Mon, Feb 15, 2021 at 6:02 PM Toke Høiland-Jørgensen < ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In lib/libxdp/xsk.c
<#92 (comment)>:
> + return ctx;
+}
+
+static void xsk_destroy_xsk_struct(struct xsk_socket *xsk)
+{
+ free(xsk->ctx);
+ free(xsk);
+}
+
+int xsk_socket__update_xskmap(struct xsk_socket *xsk, int fd)
+{
+ xsk->ctx->xsks_map_fd = fd;
+ return xsk_add_map_entry(xsk);
+}
+
+int xsk_setup_xdp_prog(int ifindex, int *xsks_map_fd)
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]
***@***.***/T/#t
This was never in scope for the libbpf implementation, but I agree that we
should provide this with libxdp if it is successfully going to serve as
this coordination point that the original code just did not offer. But I
consider this outside of this patch set. It is something we should add as a
follow up IMHO.
/Magnus
… —
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#92 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AASGUEM3JRB2GNM5NNZLWMDS7FHT7ANCNFSM4XUOHZPQ>
.
|
Magnus Karlsson <notifications@github.com> writes:
This was never in scope for the libbpf implementation, but I agree that we
should provide this with libxdp if it is successfully going to serve as
this coordination point that the original code just did not offer. But I
consider this outside of this patch set. It is something we should add as a
follow up IMHO.
OK, fair enough, we can defer this to after merge. I opened an issue so
we don't forget:
#93
|
Pushed a new version/branch |
Magnus Karlsson ***@***.***> writes:
Pushed a new version/branch
You know you can just force-push to the same source branch and github
will update the PR, right? :)
|
On Tue, Mar 23, 2021 at 11:42 AM Toke Høiland-Jørgensen ***@***.***> wrote:
Magnus Karlsson ***@***.***> writes:
> Pushed a new version/branch
You know you can just force-push to the same source branch and github
will update the PR, right? :)
Yes :-). Just did not know what you preferred. In this case, a force
push would have been warranted as it is largely a rewrite from
scratch. Threw away my changes and started with a clean libbpf, since
I was not happy with the result last time. Will force push new
versions on top of this one.
… —
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
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.