Skip to content

Commit

Permalink
Merge branch 'bpf-misc-next'
Browse files Browse the repository at this point in the history
Daniel Borkmann says:

====================
Misc BPF updates

This set cleans up ldimm64 leftovers from early eBPF days and
adds couple of test cases related to this to the verifier test
suite. It also cleans up the kallsyms spinlock (had same patch
also in queue) by relaxing it through switching to _bh variant.
It fixes up test_progs in relation to htons/ntohs and adds
accessor macros for the percpu tests in test_maps.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 28, 2017
2 parents cd5487f + f3515b5 commit 4c042a8
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 56 deletions.
9 changes: 0 additions & 9 deletions arch/arm64/net/bpf_jit_comp.c
Original file line number Diff line number Diff line change
Expand Up @@ -604,15 +604,6 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
const struct bpf_insn insn1 = insn[1];
u64 imm64;

if (insn1.code != 0 || insn1.src_reg != 0 ||
insn1.dst_reg != 0 || insn1.off != 0) {
/* Note: verifier in BPF core must catch invalid
* instructions.
*/
pr_err_once("Invalid BPF_LD_IMM64 instruction\n");
return -EINVAL;
}

imm64 = (u64)insn1.imm << 32 | (u32)imm;
emit_a64_mov_i64(dst, imm64, ctx);

Expand Down
7 changes: 0 additions & 7 deletions arch/x86/net/bpf_jit_comp.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,13 +490,6 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
break;

case BPF_LD | BPF_IMM | BPF_DW:
if (insn[1].code != 0 || insn[1].src_reg != 0 ||
insn[1].dst_reg != 0 || insn[1].off != 0) {
/* verifier must catch invalid insns */
pr_err("invalid BPF_LD_IMM64 insn\n");
return -EINVAL;
}

/* optimization: if imm64 is zero, use 'xor <dst>,<dst>'
* to save 7 bytes.
*/
Expand Down
12 changes: 4 additions & 8 deletions kernel/bpf/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,27 +394,23 @@ static bool bpf_prog_kallsyms_verify_off(const struct bpf_prog *fp)

void bpf_prog_kallsyms_add(struct bpf_prog *fp)
{
unsigned long flags;

if (!bpf_prog_kallsyms_candidate(fp) ||
!capable(CAP_SYS_ADMIN))
return;

spin_lock_irqsave(&bpf_lock, flags);
spin_lock_bh(&bpf_lock);
bpf_prog_ksym_node_add(fp->aux);
spin_unlock_irqrestore(&bpf_lock, flags);
spin_unlock_bh(&bpf_lock);
}

void bpf_prog_kallsyms_del(struct bpf_prog *fp)
{
unsigned long flags;

if (!bpf_prog_kallsyms_candidate(fp))
return;

spin_lock_irqsave(&bpf_lock, flags);
spin_lock_bh(&bpf_lock);
bpf_prog_ksym_node_del(fp->aux);
spin_unlock_irqrestore(&bpf_lock, flags);
spin_unlock_bh(&bpf_lock);
}

static struct bpf_prog *bpf_prog_kallsyms_find(unsigned long addr)
Expand Down
26 changes: 26 additions & 0 deletions tools/testing/selftests/bpf/bpf_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@
#include <string.h>
#include <errno.h>

#include <asm/byteorder.h>

#if __BYTE_ORDER == __LITTLE_ENDIAN
# define __bpf_ntohs(x) __builtin_bswap16(x)
# define __bpf_htons(x) __builtin_bswap16(x)
#elif __BYTE_ORDER == __BIG_ENDIAN
# define __bpf_ntohs(x) (x)
# define __bpf_htons(x) (x)
#else
# error "Fix your __BYTE_ORDER?!"
#endif

#define bpf_htons(x) \
(__builtin_constant_p(x) ? \
__constant_htons(x) : __bpf_htons(x))
#define bpf_ntohs(x) \
(__builtin_constant_p(x) ? \
__constant_ntohs(x) : __bpf_ntohs(x))

static inline unsigned int bpf_num_possible_cpus(void)
{
static const char *fcpu = "/sys/devices/system/cpu/possible";
Expand Down Expand Up @@ -35,4 +54,11 @@ static inline unsigned int bpf_num_possible_cpus(void)
return possible_cpus;
}

#define __bpf_percpu_val_align __attribute__((__aligned__(8)))

#define BPF_DECLARE_PERCPU(type, name) \
struct { type v; /* padding */ } __bpf_percpu_val_align \
name[bpf_num_possible_cpus()]
#define bpf_percpu(name, cpu) name[(cpu)].v

#endif /* __BPF_UTIL__ */
11 changes: 5 additions & 6 deletions tools/testing/selftests/bpf/test_l4lb.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@
#include <linux/udp.h>
#include "bpf_helpers.h"
#include "test_iptunnel_common.h"
#include "bpf_util.h"

#define htons __builtin_bswap16
#define ntohs __builtin_bswap16
int _version SEC("version") = 1;

static inline __u32 rol32(__u32 word, unsigned int shift)
Expand Down Expand Up @@ -355,7 +354,7 @@ static __always_inline int process_packet(void *data, __u64 off, void *data_end,
iph_len = sizeof(struct ipv6hdr);
protocol = ip6h->nexthdr;
pckt.proto = protocol;
pkt_bytes = ntohs(ip6h->payload_len);
pkt_bytes = bpf_ntohs(ip6h->payload_len);
off += iph_len;
if (protocol == IPPROTO_FRAGMENT) {
return TC_ACT_SHOT;
Expand All @@ -377,7 +376,7 @@ static __always_inline int process_packet(void *data, __u64 off, void *data_end,

protocol = iph->protocol;
pckt.proto = protocol;
pkt_bytes = ntohs(iph->tot_len);
pkt_bytes = bpf_ntohs(iph->tot_len);
off += IPV4_HDR_LEN_NO_OPT;

if (iph->frag_off & PCKT_FRAGMENTED)
Expand Down Expand Up @@ -464,9 +463,9 @@ int balancer_ingress(struct __sk_buff *ctx)
if (data + nh_off > data_end)
return TC_ACT_SHOT;
eth_proto = eth->eth_proto;
if (eth_proto == htons(ETH_P_IP))
if (eth_proto == bpf_htons(ETH_P_IP))
return process_packet(data, nh_off, data_end, false, ctx);
else if (eth_proto == htons(ETH_P_IPV6))
else if (eth_proto == bpf_htons(ETH_P_IPV6))
return process_packet(data, nh_off, data_end, true, ctx);
else
return TC_ACT_SHOT;
Expand Down
37 changes: 20 additions & 17 deletions tools/testing/selftests/bpf/test_maps.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,20 +137,20 @@ static void test_hashmap_sizes(int task, void *data)
static void test_hashmap_percpu(int task, void *data)
{
unsigned int nr_cpus = bpf_num_possible_cpus();
long long value[nr_cpus];
BPF_DECLARE_PERCPU(long, value);
long long key, next_key, first_key;
int expected_key_mask = 0;
int fd, i;

fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key),
sizeof(value[0]), 2, map_flags);
sizeof(bpf_percpu(value, 0)), 2, map_flags);
if (fd < 0) {
printf("Failed to create hashmap '%s'!\n", strerror(errno));
exit(1);
}

for (i = 0; i < nr_cpus; i++)
value[i] = i + 100;
bpf_percpu(value, i) = i + 100;

key = 1;
/* Insert key=1 element. */
Expand All @@ -170,8 +170,9 @@ static void test_hashmap_percpu(int task, void *data)
/* Check that key=1 can be found. Value could be 0 if the lookup
* was run from a different CPU.
*/
value[0] = 1;
assert(bpf_map_lookup_elem(fd, &key, value) == 0 && value[0] == 100);
bpf_percpu(value, 0) = 1;
assert(bpf_map_lookup_elem(fd, &key, value) == 0 &&
bpf_percpu(value, 0) == 100);

key = 2;
/* Check that key=2 is not found. */
Expand Down Expand Up @@ -211,7 +212,7 @@ static void test_hashmap_percpu(int task, void *data)
assert(bpf_map_lookup_elem(fd, &next_key, value) == 0);

for (i = 0; i < nr_cpus; i++)
assert(value[i] == i + 100);
assert(bpf_percpu(value, i) == i + 100);

key = next_key;
}
Expand Down Expand Up @@ -296,34 +297,36 @@ static void test_arraymap(int task, void *data)
static void test_arraymap_percpu(int task, void *data)
{
unsigned int nr_cpus = bpf_num_possible_cpus();
BPF_DECLARE_PERCPU(long, values);
int key, next_key, fd, i;
long long values[nr_cpus];

fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
sizeof(values[0]), 2, 0);
sizeof(bpf_percpu(values, 0)), 2, 0);
if (fd < 0) {
printf("Failed to create arraymap '%s'!\n", strerror(errno));
exit(1);
}

for (i = 0; i < nr_cpus; i++)
values[i] = i + 100;
bpf_percpu(values, i) = i + 100;

key = 1;
/* Insert key=1 element. */
assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);

values[0] = 0;
bpf_percpu(values, 0) = 0;
assert(bpf_map_update_elem(fd, &key, values, BPF_NOEXIST) == -1 &&
errno == EEXIST);

/* Check that key=1 can be found. */
assert(bpf_map_lookup_elem(fd, &key, values) == 0 && values[0] == 100);
assert(bpf_map_lookup_elem(fd, &key, values) == 0 &&
bpf_percpu(values, 0) == 100);

key = 0;
/* Check that key=0 is also found and zero initialized. */
assert(bpf_map_lookup_elem(fd, &key, values) == 0 &&
values[0] == 0 && values[nr_cpus - 1] == 0);
bpf_percpu(values, 0) == 0 &&
bpf_percpu(values, nr_cpus - 1) == 0);

/* Check that key=2 cannot be inserted due to max_entries limit. */
key = 2;
Expand Down Expand Up @@ -353,35 +356,35 @@ static void test_arraymap_percpu(int task, void *data)
static void test_arraymap_percpu_many_keys(void)
{
unsigned int nr_cpus = bpf_num_possible_cpus();
BPF_DECLARE_PERCPU(long, values);
/* nr_keys is not too large otherwise the test stresses percpu
* allocator more than anything else
*/
unsigned int nr_keys = 2000;
long long values[nr_cpus];
int key, fd, i;

fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
sizeof(values[0]), nr_keys, 0);
sizeof(bpf_percpu(values, 0)), nr_keys, 0);
if (fd < 0) {
printf("Failed to create per-cpu arraymap '%s'!\n",
strerror(errno));
exit(1);
}

for (i = 0; i < nr_cpus; i++)
values[i] = i + 10;
bpf_percpu(values, i) = i + 10;

for (key = 0; key < nr_keys; key++)
assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);

for (key = 0; key < nr_keys; key++) {
for (i = 0; i < nr_cpus; i++)
values[i] = 0;
bpf_percpu(values, i) = 0;

assert(bpf_map_lookup_elem(fd, &key, values) == 0);

for (i = 0; i < nr_cpus; i++)
assert(values[i] == i + 10);
assert(bpf_percpu(values, i) == i + 10);
}

close(fd);
Expand Down
6 changes: 3 additions & 3 deletions tools/testing/selftests/bpf/test_pkt_access.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
#include <linux/tcp.h>
#include <linux/pkt_cls.h>
#include "bpf_helpers.h"
#include "bpf_util.h"

#define _htons __builtin_bswap16
#define barrier() __asm__ __volatile__("": : :"memory")
int _version SEC("version") = 1;

Expand All @@ -32,15 +32,15 @@ int process(struct __sk_buff *skb)
if (eth + 1 > data_end)
return TC_ACT_SHOT;

if (eth->h_proto == _htons(ETH_P_IP)) {
if (eth->h_proto == bpf_htons(ETH_P_IP)) {
struct iphdr *iph = (struct iphdr *)(eth + 1);

if (iph + 1 > data_end)
return TC_ACT_SHOT;
ihl_len = iph->ihl * 4;
proto = iph->protocol;
tcp = (struct tcphdr *)((void *)(iph) + ihl_len);
} else if (eth->h_proto == _htons(ETH_P_IPV6)) {
} else if (eth->h_proto == bpf_htons(ETH_P_IPV6)) {
struct ipv6hdr *ip6h = (struct ipv6hdr *)(eth + 1);

if (ip6h + 1 > data_end)
Expand Down
10 changes: 4 additions & 6 deletions tools/testing/selftests/bpf/test_progs.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ typedef __u16 __sum16;
#include "test_iptunnel_common.h"
#include "bpf_util.h"

#define _htons __builtin_bswap16

static int error_cnt, pass_cnt;

#define MAGIC_BYTES 123
Expand All @@ -42,10 +40,10 @@ static struct {
struct iphdr iph;
struct tcphdr tcp;
} __packed pkt_v4 = {
.eth.h_proto = _htons(ETH_P_IP),
.eth.h_proto = bpf_htons(ETH_P_IP),
.iph.ihl = 5,
.iph.protocol = 6,
.iph.tot_len = _htons(MAGIC_BYTES),
.iph.tot_len = bpf_htons(MAGIC_BYTES),
.tcp.urg_ptr = 123,
};

Expand All @@ -55,9 +53,9 @@ static struct {
struct ipv6hdr iph;
struct tcphdr tcp;
} __packed pkt_v6 = {
.eth.h_proto = _htons(ETH_P_IPV6),
.eth.h_proto = bpf_htons(ETH_P_IPV6),
.iph.nexthdr = 6,
.iph.payload_len = _htons(MAGIC_BYTES),
.iph.payload_len = bpf_htons(MAGIC_BYTES),
.tcp.urg_ptr = 123,
};

Expand Down
Loading

0 comments on commit 4c042a8

Please sign in to comment.