Skip to content

Commit

Permalink
loader: Fix --force mode for cross-native/generic loading
Browse files Browse the repository at this point in the history
Just unsetting the XDP_FLAGS_UPDATE_IF_NOEXIST is not enough to force-load
a new XDP program, if the program already loaded is a different type (i.e,
loading a generic XDP program won't unload a native mode program). Handle
this, by reacting to the EEXIST error code when --force is set, by
unloading the opposite program type.

Fixes xdp-project#26.

Signed-off-by: Toke Høiland-Jørgensen <[email protected]>
  • Loading branch information
tohojo committed Apr 15, 2019
1 parent 442b09c commit 0e5fe28
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 0 deletions.
16 changes: 16 additions & 0 deletions basic01-xdp-pass/xdp_pass_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,29 @@ int xdp_link_attach(int ifindex, __u32 xdp_flags, int prog_fd)

/* libbpf provide the XDP net_device link-level hook attach helper */
err = bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags);
if (err == -EEXIST && !(xdp_flags & XDP_FLAGS_UPDATE_IF_NOEXIST)) {
/* Force mode didn't work, probably because a program of the
* opposite type is loaded. Let's unload that and try loading
* again.
*/

__u32 old_flags = xdp_flags;

xdp_flags &= ~XDP_FLAGS_MODES;
xdp_flags |= (old_flags & XDP_FLAGS_SKB_MODE) ? XDP_FLAGS_DRV_MODE : XDP_FLAGS_SKB_MODE;
err = bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
if (!err)
err = bpf_set_link_xdp_fd(ifindex, prog_fd, old_flags);
}

if (err < 0) {
fprintf(stderr, "ERR: "
"ifindex(%d) link set xdp fd failed (%d): %s\n",
ifindex, -err, strerror(-err));

switch (-err) {
case EBUSY:
case EEXIST:
fprintf(stderr, "Hint: XDP already loaded on device"
" use --force to swap/replace\n");
break;
Expand Down
15 changes: 15 additions & 0 deletions common/common_user_bpf_xdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,28 @@ int xdp_link_attach(int ifindex, __u32 xdp_flags, int prog_fd)

/* libbpf provide the XDP net_device link-level hook attach helper */
err = bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags);
if (err == -EEXIST && !(xdp_flags & XDP_FLAGS_UPDATE_IF_NOEXIST)) {
/* Force mode didn't work, probably because a program of the
* opposite type is loaded. Let's unload that and try loading
* again.
*/

__u32 old_flags = xdp_flags;

xdp_flags &= ~XDP_FLAGS_MODES;
xdp_flags |= (old_flags & XDP_FLAGS_SKB_MODE) ? XDP_FLAGS_DRV_MODE : XDP_FLAGS_SKB_MODE;
err = bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
if (!err)
err = bpf_set_link_xdp_fd(ifindex, prog_fd, old_flags);
}
if (err < 0) {
fprintf(stderr, "ERR: "
"ifindex(%d) link set xdp fd failed (%d): %s\n",
ifindex, -err, strerror(-err));

switch (-err) {
case EBUSY:
case EEXIST:
fprintf(stderr, "Hint: XDP already loaded on device"
" use --force to swap/replace\n");
break;
Expand Down

0 comments on commit 0e5fe28

Please sign in to comment.