Skip to content

Commit

Permalink
bpf: sockmap, test FIONREAD returns correct bytes in rx buffer with d…
Browse files Browse the repository at this point in the history
…rops

When BPF program drops pkts the sockmap logic 'eats' the packet and
updates copied_seq. In the PASS case where the sk_buff is accepted
we update copied_seq from recvmsg path so we need a new test to
handle the drop case.

Original patch series broke this resulting in

test_sockmap_skb_verdict_fionread:PASS:ioctl(FIONREAD) error 0 nsec
test_sockmap_skb_verdict_fionread:FAIL:ioctl(FIONREAD) unexpected ioctl(FIONREAD): actual 1503041772 != expected 256
torvalds#176/17  sockmap_basic/sockmap skb_verdict fionread on drop:FAIL

After updated patch with fix.

torvalds#176/16  sockmap_basic/sockmap skb_verdict fionread:OK
torvalds#176/17  sockmap_basic/sockmap skb_verdict fionread on drop:OK

Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
Signed-off-by: John Fastabend <john.fastabend@gmail.com>
  • Loading branch information
jrfastab authored and intel-lab-lkp committed May 23, 2023
1 parent 49733b1 commit 2757607
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 13 deletions.
47 changes: 34 additions & 13 deletions tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "test_sockmap_skb_verdict_attach.skel.h"
#include "test_sockmap_progs_query.skel.h"
#include "test_sockmap_pass_prog.skel.h"
#include "test_sockmap_drop_prog.skel.h"
#include "bpf_iter_sockmap.skel.h"

#include "sockmap_helpers.h"
Expand Down Expand Up @@ -410,19 +411,31 @@ static void test_sockmap_skb_verdict_shutdown(void)
test_sockmap_pass_prog__destroy(skel);
}

static void test_sockmap_skb_verdict_fionread(void)
static void test_sockmap_skb_verdict_fionread(bool pass_prog)
{
int expected, zero = 0, sent, recvd, avail;
int err, map, verdict, s, c0, c1, p0, p1;
struct test_sockmap_pass_prog *skel;
int zero = 0, sent, recvd, avail;
struct test_sockmap_pass_prog *pass;
struct test_sockmap_drop_prog *drop;
char buf[256] = "0123456789";

skel = test_sockmap_pass_prog__open_and_load();
if (!ASSERT_OK_PTR(skel, "open_and_load"))
return;
if (pass_prog) {
pass = test_sockmap_pass_prog__open_and_load();
if (!ASSERT_OK_PTR(pass, "open_and_load"))
return;
verdict = bpf_program__fd(pass->progs.prog_skb_verdict);
map = bpf_map__fd(pass->maps.sock_map_rx);
expected = sizeof(buf);
} else {
drop = test_sockmap_drop_prog__open_and_load();
if (!ASSERT_OK_PTR(drop, "open_and_load"))
return;
verdict = bpf_program__fd(drop->progs.prog_skb_verdict);
map = bpf_map__fd(drop->maps.sock_map_rx);
/* On drop data is consumed immediately and copied_seq inc'd */
expected = 0;
}

verdict = bpf_program__fd(skel->progs.prog_skb_verdict);
map = bpf_map__fd(skel->maps.sock_map_rx);

err = bpf_prog_attach(verdict, map, BPF_SK_SKB_STREAM_VERDICT, 0);
if (!ASSERT_OK(err, "bpf_prog_attach"))
Expand All @@ -443,17 +456,23 @@ static void test_sockmap_skb_verdict_fionread(void)
ASSERT_EQ(sent, sizeof(buf), "xsend(p0)");
err = ioctl(c1, FIONREAD, &avail);
ASSERT_OK(err, "ioctl(FIONREAD) error");
ASSERT_EQ(avail, sizeof(buf), "ioctl(FIONREAD)");
recvd = recv_timeout(c1, &buf, sizeof(buf), SOCK_NONBLOCK, IO_TIMEOUT_SEC);
ASSERT_EQ(recvd, sizeof(buf), "recv_timeout(c0)");
ASSERT_EQ(avail, expected, "ioctl(FIONREAD)");
/* On DROP test there will be no data to read */
if (pass_prog) {
recvd = recv_timeout(c1, &buf, sizeof(buf), SOCK_NONBLOCK, IO_TIMEOUT_SEC);
ASSERT_EQ(recvd, sizeof(buf), "recv_timeout(c0)");
}

out_close:
close(c0);
close(p0);
close(c1);
close(p1);
out:
test_sockmap_pass_prog__destroy(skel);
if (pass_prog)
test_sockmap_pass_prog__destroy(pass);
else
test_sockmap_drop_prog__destroy(drop);
}

void test_sockmap_basic(void)
Expand Down Expand Up @@ -493,5 +512,7 @@ void test_sockmap_basic(void)
if (test__start_subtest("sockmap skb_verdict shutdown"))
test_sockmap_skb_verdict_shutdown();
if (test__start_subtest("sockmap skb_verdict fionread"))
test_sockmap_skb_verdict_fionread();
test_sockmap_skb_verdict_fionread(true);
if (test__start_subtest("sockmap skb_verdict fionread on drop"))
test_sockmap_skb_verdict_fionread(false);
}
32 changes: 32 additions & 0 deletions tools/testing/selftests/bpf/progs/test_sockmap_drop_prog.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h>

struct {
__uint(type, BPF_MAP_TYPE_SOCKMAP);
__uint(max_entries, 20);
__type(key, int);
__type(value, int);
} sock_map_rx SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_SOCKMAP);
__uint(max_entries, 20);
__type(key, int);
__type(value, int);
} sock_map_tx SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_SOCKMAP);
__uint(max_entries, 20);
__type(key, int);
__type(value, int);
} sock_map_msg SEC(".maps");

SEC("sk_skb")
int prog_skb_verdict(struct __sk_buff *skb)
{
return SK_DROP;
}

char _license[] SEC("license") = "GPL";

0 comments on commit 2757607

Please sign in to comment.