On 12/18/17 10:21 PM, Lawrence Brakmo wrote:
+#define SOCK_OPS_SET_FIELD(FIELD_NAME, OBJ) \ + do { \ + int reg = BPF_REG_9; \ + BUILD_BUG_ON(FIELD_SIZEOF(OBJ, FIELD_NAME) > \ + FIELD_SIZEOF(struct bpf_sock_ops, FIELD_NAME)); \ + while (si->dst_reg == reg || si->src_reg == reg) \ + reg--; \ + *insn++ = BPF_STX_MEM(BPF_DW, si->dst_reg, reg, \ + offsetof(struct bpf_sock_ops_kern, \ + temp)); \ + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \ + struct bpf_sock_ops_kern, \ + is_fullsock), \ + reg, si->dst_reg, \ + offsetof(struct bpf_sock_ops_kern, \ + is_fullsock)); \ + *insn++ = BPF_JMP_IMM(BPF_JEQ, reg, 0, 2); \ + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \ + struct bpf_sock_ops_kern, sk),\ + reg, si->dst_reg, \ + offsetof(struct bpf_sock_ops_kern, sk));\ + *insn++ = BPF_STX_MEM(BPF_FIELD_SIZEOF(OBJ, FIELD_NAME), \ + reg, si->src_reg, \ + offsetof(OBJ, FIELD_NAME)); \ + *insn++ = BPF_LDX_MEM(BPF_DW, reg, si->dst_reg, \ + offsetof(struct bpf_sock_ops_kern, \ + temp)); \ + } while (0)
that's neat. I like it. I guess the prog can check is_fullsock on its own to see whether writes will fail or not, so JEQ above is ok. Only while() loop looks a bit scary. May be replace with two 'if' ? if (si->dst_reg == reg || si->src_reg == reg) reg --; if (si->dst_reg == reg || si->src_reg == reg) reg --; so it's clear that tmp reg will be reg_7, 8 or 9.