blob: 1d9a310e71e594fbfc26c14e7e41581397b83136 [file] [log] [blame]
Alexei Starovoitov68828042017-03-30 21:45:41 -07001/* Copyright (c) 2017 Facebook
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 */
7#include <stdio.h>
8#include <unistd.h>
9#include <errno.h>
10#include <string.h>
11#include <assert.h>
12#include <stdlib.h>
13
14#include <linux/types.h>
15typedef __u16 __sum16;
16#include <arpa/inet.h>
17#include <linux/if_ether.h>
18#include <linux/if_packet.h>
19#include <linux/ip.h>
20#include <linux/ipv6.h>
21#include <linux/tcp.h>
22
23#include <sys/wait.h>
24#include <sys/resource.h>
25
26#include <linux/bpf.h>
27#include <linux/err.h>
28#include <bpf/bpf.h>
29#include <bpf/libbpf.h>
30
31#define _htons __builtin_bswap16
32
33static int error_cnt, pass_cnt;
34
35/* ipv4 test vector */
36static struct {
37 struct ethhdr eth;
38 struct iphdr iph;
39 struct tcphdr tcp;
40} __packed pkt_v4 = {
41 .eth.h_proto = _htons(ETH_P_IP),
42 .iph.ihl = 5,
43 .iph.protocol = 6,
44 .tcp.urg_ptr = 123,
45};
46
47/* ipv6 test vector */
48static struct {
49 struct ethhdr eth;
50 struct ipv6hdr iph;
51 struct tcphdr tcp;
52} __packed pkt_v6 = {
53 .eth.h_proto = _htons(ETH_P_IPV6),
54 .iph.nexthdr = 6,
55 .tcp.urg_ptr = 123,
56};
57
58#define CHECK(condition, tag, format...) ({ \
59 int __ret = !!(condition); \
60 if (__ret) { \
61 error_cnt++; \
62 printf("%s:FAIL:%s ", __func__, tag); \
63 printf(format); \
64 } else { \
65 pass_cnt++; \
66 printf("%s:PASS:%s %d nsec\n", __func__, tag, duration);\
67 } \
68})
69
70static int bpf_prog_load(const char *file, enum bpf_prog_type type,
71 struct bpf_object **pobj, int *prog_fd)
72{
73 struct bpf_program *prog;
74 struct bpf_object *obj;
75 int err;
76
77 obj = bpf_object__open(file);
78 if (IS_ERR(obj)) {
79 error_cnt++;
80 return -ENOENT;
81 }
82
83 prog = bpf_program__next(NULL, obj);
84 if (!prog) {
85 bpf_object__close(obj);
86 error_cnt++;
87 return -ENOENT;
88 }
89
90 bpf_program__set_type(prog, type);
91 err = bpf_object__load(obj);
92 if (err) {
93 bpf_object__close(obj);
94 error_cnt++;
95 return -EINVAL;
96 }
97
98 *pobj = obj;
99 *prog_fd = bpf_program__fd(prog);
100 return 0;
101}
102
103static void test_pkt_access(void)
104{
105 const char *file = "./test_pkt_access.o";
106 struct bpf_object *obj;
107 __u32 duration, retval;
108 int err, prog_fd;
109
110 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
111 if (err)
112 return;
113
114 err = bpf_prog_test_run(prog_fd, 100000, &pkt_v4, sizeof(pkt_v4),
115 NULL, NULL, &retval, &duration);
116 CHECK(err || errno || retval, "ipv4",
117 "err %d errno %d retval %d duration %d\n",
118 err, errno, retval, duration);
119
120 err = bpf_prog_test_run(prog_fd, 100000, &pkt_v6, sizeof(pkt_v6),
121 NULL, NULL, &retval, &duration);
122 CHECK(err || errno || retval, "ipv6",
123 "err %d errno %d retval %d duration %d\n",
124 err, errno, retval, duration);
125 bpf_object__close(obj);
126}
127
128int main(void)
129{
130 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
131
132 setrlimit(RLIMIT_MEMLOCK, &rinf);
133
134 test_pkt_access();
135
136 printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt);
137 return 0;
138}