Commit dc503a8a authored by Edward Cree's avatar Edward Cree Committed by David S. Miller

bpf/verifier: track liveness for pruning

State of a register doesn't matter if it wasn't read in reaching an exit;
 a write screens off all reads downstream of it from all explored_states
 upstream of it.
This allows us to prune many more branches; here are some processed insn
 counts for some Cilium programs:
Program                  before  after
bpf_lb_opt_-DLB_L3.o       6515   3361
bpf_lb_opt_-DLB_L4.o       8976   5176
bpf_lb_opt_-DUNKNOWN.o     2960   1137
bpf_lxc_opt_-DDROP_ALL.o  95412  48537
bpf_lxc_opt_-DUNKNOWN.o  141706  78718
bpf_netdev.o              24251  17995
bpf_overlay.o             10999   9385

The runtime is also improved; here are 'time' results in ms:
Program                  before  after
bpf_lb_opt_-DLB_L3.o         24      6
bpf_lb_opt_-DLB_L4.o         26     11
bpf_lb_opt_-DUNKNOWN.o       11      2
bpf_lxc_opt_-DDROP_ALL.o   1288    139
bpf_lxc_opt_-DUNKNOWN.o    1768    234
bpf_netdev.o                 62     31
bpf_overlay.o                15     13
Signed-off-by: default avatarEdward Cree <ecree@solarflare.com>
Acked-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0461b766
...@@ -21,6 +21,12 @@ ...@@ -21,6 +21,12 @@
*/ */
#define BPF_MAX_VAR_SIZ INT_MAX #define BPF_MAX_VAR_SIZ INT_MAX
enum bpf_reg_liveness {
REG_LIVE_NONE = 0, /* reg hasn't been read or written this branch */
REG_LIVE_READ, /* reg was read, so we're sensitive to initial value */
REG_LIVE_WRITTEN, /* reg was written first, screening off later reads */
};
struct bpf_reg_state { struct bpf_reg_state {
enum bpf_reg_type type; enum bpf_reg_type type;
union { union {
...@@ -40,7 +46,7 @@ struct bpf_reg_state { ...@@ -40,7 +46,7 @@ struct bpf_reg_state {
* came from, when one is tested for != NULL. * came from, when one is tested for != NULL.
*/ */
u32 id; u32 id;
/* These five fields must be last. See states_equal() */ /* Ordering of fields matters. See states_equal() */
/* For scalar types (SCALAR_VALUE), this represents our knowledge of /* For scalar types (SCALAR_VALUE), this represents our knowledge of
* the actual value. * the actual value.
* For pointer types, this represents the variable part of the offset * For pointer types, this represents the variable part of the offset
...@@ -57,6 +63,8 @@ struct bpf_reg_state { ...@@ -57,6 +63,8 @@ struct bpf_reg_state {
s64 smax_value; /* maximum possible (s64)value */ s64 smax_value; /* maximum possible (s64)value */
u64 umin_value; /* minimum possible (u64)value */ u64 umin_value; /* minimum possible (u64)value */
u64 umax_value; /* maximum possible (u64)value */ u64 umax_value; /* maximum possible (u64)value */
/* This field must be last, for states_equal() reasons. */
enum bpf_reg_liveness live;
}; };
enum bpf_stack_slot_type { enum bpf_stack_slot_type {
...@@ -74,6 +82,7 @@ struct bpf_verifier_state { ...@@ -74,6 +82,7 @@ struct bpf_verifier_state {
struct bpf_reg_state regs[MAX_BPF_REG]; struct bpf_reg_state regs[MAX_BPF_REG];
u8 stack_slot_type[MAX_BPF_STACK]; u8 stack_slot_type[MAX_BPF_STACK];
struct bpf_reg_state spilled_regs[MAX_BPF_STACK / BPF_REG_SIZE]; struct bpf_reg_state spilled_regs[MAX_BPF_STACK / BPF_REG_SIZE];
struct bpf_verifier_state *parent;
}; };
/* linked list of verifier states used to prune search */ /* linked list of verifier states used to prune search */
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment