Message ID | 20210616203448.995314-2-tannerlove.kernel@gmail.com |
---|---|
State | New |
Headers | show |
Series | [net-next,v7,1/3] net: flow_dissector: extend bpf flow dissector support with vnet hdr | expand |
Hi Tanner, Thank you for the patch! Yet something to improve: [auto build test ERROR on net-next/master] url: https://github.com/0day-ci/linux/commits/Tanner-Love/virtio_net-add-optional-flow-dissection-in-virtio_net_hdr_to_skb/20210617-082208 base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 0c33795231bff5df410bd405b569c66851e92d4b config: m68k-randconfig-r023-20210617 (attached as .config) compiler: m68k-linux-gcc (GCC) 9.3.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/b03a1eb684b925a09ae011d0e620d98ebf3b0abd git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Tanner-Love/virtio_net-add-optional-flow-dissection-in-virtio_net_hdr_to_skb/20210617-082208 git checkout b03a1eb684b925a09ae011d0e620d98ebf3b0abd # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=m68k If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All error/warnings (new ones prefixed by >>): net/core/filter.c: In function 'bpf_flow_keys_is_valid_access': >> net/core/filter.c:7900:15: error: implicit declaration of function 'bpf_get_btf_vmlinux' [-Werror=implicit-function-declaration] 7900 | info->btf = bpf_get_btf_vmlinux(); | ^~~~~~~~~~~~~~~~~~~ >> net/core/filter.c:7900:13: warning: assignment to 'struct btf *' from 'int' makes pointer from integer without a cast [-Wint-conversion] 7900 | info->btf = bpf_get_btf_vmlinux(); | ^ cc1: some warnings being treated as errors vim +/bpf_get_btf_vmlinux +7900 net/core/filter.c 7884 7885 int bpf_flow_keys_is_valid_access(int off, int size, enum bpf_access_type t, 7886 struct bpf_insn_access_aux *info) 7887 { 7888 if (off < 0 || 7889 (u64)off + size > offsetofend(struct bpf_flow_keys, vhdr)) 7890 return -EACCES; 7891 7892 switch (off) { 7893 case bpf_ctx_range_ptr(struct bpf_flow_keys, vhdr): 7894 if (t == BPF_WRITE || off % size != 0 || size != sizeof(__u64)) 7895 return -EACCES; 7896 7897 if (!bpf_flow_dissector_btf_ids[0]) 7898 return -EINVAL; 7899 > 7900 info->btf = bpf_get_btf_vmlinux(); 7901 info->reg_type = PTR_TO_BTF_ID_OR_NULL; 7902 info->btf_id = bpf_flow_dissector_btf_ids[0]; 7903 7904 break; 7905 } 7906 7907 return 0; 7908 } 7909 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Hi Tanner, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on net-next/master] url: https://github.com/0day-ci/linux/commits/Tanner-Love/virtio_net-add-optional-flow-dissection-in-virtio_net_hdr_to_skb/20210617-082208 base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 0c33795231bff5df410bd405b569c66851e92d4b config: x86_64-randconfig-a014-20210617 (attached as .config) compiler: clang version 13.0.0 (https://github.com/llvm/llvm-project 64720f57bea6a6bf033feef4a5751ab9c0c3b401) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install x86_64 cross compiling tool for clang build # apt-get install binutils-x86-64-linux-gnu # https://github.com/0day-ci/linux/commit/b03a1eb684b925a09ae011d0e620d98ebf3b0abd git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Tanner-Love/virtio_net-add-optional-flow-dissection-in-virtio_net_hdr_to_skb/20210617-082208 git checkout b03a1eb684b925a09ae011d0e620d98ebf3b0abd # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): net/core/filter.c:7900:15: error: implicit declaration of function 'bpf_get_btf_vmlinux' [-Werror,-Wimplicit-function-declaration] info->btf = bpf_get_btf_vmlinux(); ^ >> net/core/filter.c:7900:13: warning: incompatible integer to pointer conversion assigning to 'struct btf *' from 'int' [-Wint-conversion] info->btf = bpf_get_btf_vmlinux(); ^ ~~~~~~~~~~~~~~~~~~~~~ 1 warning and 1 error generated. vim +7900 net/core/filter.c 7884 7885 int bpf_flow_keys_is_valid_access(int off, int size, enum bpf_access_type t, 7886 struct bpf_insn_access_aux *info) 7887 { 7888 if (off < 0 || 7889 (u64)off + size > offsetofend(struct bpf_flow_keys, vhdr)) 7890 return -EACCES; 7891 7892 switch (off) { 7893 case bpf_ctx_range_ptr(struct bpf_flow_keys, vhdr): 7894 if (t == BPF_WRITE || off % size != 0 || size != sizeof(__u64)) 7895 return -EACCES; 7896 7897 if (!bpf_flow_dissector_btf_ids[0]) 7898 return -EINVAL; 7899 > 7900 info->btf = bpf_get_btf_vmlinux(); 7901 info->reg_type = PTR_TO_BTF_ID_OR_NULL; 7902 info->btf_id = bpf_flow_dissector_btf_ids[0]; 7903 7904 break; 7905 } 7906 7907 return 0; 7908 } 7909 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Hi Tanner, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on net-next/master] url: https://github.com/0day-ci/linux/commits/Tanner-Love/virtio_net-add-optional-flow-dissection-in-virtio_net_hdr_to_skb/20210617-082208 base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 0c33795231bff5df410bd405b569c66851e92d4b config: s390-randconfig-s031-20210617 (attached as .config) compiler: s390-linux-gcc (GCC) 9.3.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # apt-get install sparse # sparse version: v0.6.3-341-g8af24329-dirty # https://github.com/0day-ci/linux/commit/b03a1eb684b925a09ae011d0e620d98ebf3b0abd git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Tanner-Love/virtio_net-add-optional-flow-dissection-in-virtio_net_hdr_to_skb/20210617-082208 git checkout b03a1eb684b925a09ae011d0e620d98ebf3b0abd # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' W=1 ARCH=s390 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> sparse warnings: (new ones prefixed by >>) >> net/core/flow_dissector.c:882:40: sparse: sparse: incorrect type in assignment (different base types) @@ expected restricted __virtio16 [assigned] [usertype] hdr_len @@ got unsigned short @@ net/core/flow_dissector.c:882:40: sparse: expected restricted __virtio16 [assigned] [usertype] hdr_len net/core/flow_dissector.c:882:40: sparse: got unsigned short >> net/core/flow_dissector.c:884:41: sparse: sparse: incorrect type in assignment (different base types) @@ expected restricted __virtio16 [assigned] [usertype] gso_size @@ got unsigned short @@ net/core/flow_dissector.c:884:41: sparse: expected restricted __virtio16 [assigned] [usertype] gso_size net/core/flow_dissector.c:884:41: sparse: got unsigned short >> net/core/flow_dissector.c:886:43: sparse: sparse: incorrect type in assignment (different base types) @@ expected restricted __virtio16 [assigned] [usertype] csum_start @@ got unsigned short @@ net/core/flow_dissector.c:886:43: sparse: expected restricted __virtio16 [assigned] [usertype] csum_start net/core/flow_dissector.c:886:43: sparse: got unsigned short >> net/core/flow_dissector.c:888:44: sparse: sparse: incorrect type in assignment (different base types) @@ expected restricted __virtio16 [assigned] [usertype] csum_offset @@ got unsigned short @@ net/core/flow_dissector.c:888:44: sparse: expected restricted __virtio16 [assigned] [usertype] csum_offset net/core/flow_dissector.c:888:44: sparse: got unsigned short vim +882 net/core/flow_dissector.c 866 867 bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx, 868 __be16 proto, int nhoff, int hlen, unsigned int flags, 869 const struct virtio_net_hdr *vhdr, 870 bool vhdr_is_little_endian) 871 { 872 struct bpf_flow_keys *flow_keys = ctx->flow_keys; 873 u32 result; 874 875 /* vnet hdr is either machine endian (virtio spec < v1) or le (>= v1) */ 876 #if defined(__BIG_ENDIAN_BITFIELD) 877 struct virtio_net_hdr vnet_hdr_local; 878 879 if (vhdr && vhdr_is_little_endian) { 880 vnet_hdr_local.flags = vhdr->flags; 881 vnet_hdr_local.gso_type = vhdr->gso_type; > 882 vnet_hdr_local.hdr_len = __virtio16_to_cpu(false, 883 vhdr->hdr_len); > 884 vnet_hdr_local.gso_size = __virtio16_to_cpu(false, 885 vhdr->gso_size); > 886 vnet_hdr_local.csum_start = __virtio16_to_cpu(false, 887 vhdr->csum_start); > 888 vnet_hdr_local.csum_offset = __virtio16_to_cpu(false, 889 vhdr->csum_offset); 890 vhdr = &vnet_hdr_local; 891 } 892 #endif 893 894 /* Pass parameters to the BPF program */ 895 memset(flow_keys, 0, sizeof(*flow_keys)); 896 flow_keys->n_proto = proto; 897 flow_keys->nhoff = nhoff; 898 flow_keys->thoff = flow_keys->nhoff; 899 flow_keys->vhdr = vhdr; 900 901 BUILD_BUG_ON((int)BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG != 902 (int)FLOW_DISSECTOR_F_PARSE_1ST_FRAG); 903 BUILD_BUG_ON((int)BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL != 904 (int)FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL); 905 BUILD_BUG_ON((int)BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP != 906 (int)FLOW_DISSECTOR_F_STOP_AT_ENCAP); 907 flow_keys->flags = flags; 908 909 result = bpf_prog_run_pin_on_cpu(prog, ctx); 910 911 flow_keys->nhoff = clamp_t(u16, flow_keys->nhoff, nhoff, hlen); 912 flow_keys->thoff = clamp_t(u16, flow_keys->thoff, 913 flow_keys->nhoff, hlen); 914 915 return result == BPF_OK; 916 } 917 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index eb79a9f05914..36993636d56d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3554,7 +3554,7 @@ static bool bond_flow_dissect(struct bonding *bond, struct sk_buff *skb, case BOND_XMIT_POLICY_ENCAP34: memset(fk, 0, sizeof(*fk)); return __skb_flow_dissect(NULL, skb, &flow_keys_bonding, - fk, NULL, 0, 0, 0, 0); + fk, NULL, 0, 0, 0, 0, NULL, false); default: break; } diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 9dc44ba97584..e6980da0b469 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1998,6 +1998,8 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type, struct bpf_insn *insn_buf, struct bpf_prog *prog, u32 *target_size); +int bpf_flow_keys_is_valid_access(int off, int size, enum bpf_access_type t, + struct bpf_insn_access_aux *info); #else static inline bool bpf_sock_common_is_valid_access(int off, int size, enum bpf_access_type type, @@ -2019,6 +2021,12 @@ static inline u32 bpf_sock_convert_ctx_access(enum bpf_access_type type, { return 0; } +static inline int bpf_flow_keys_is_valid_access(int off, int size, + enum bpf_access_type t, + struct bpf_insn_access_aux *info) +{ + return -EINVAL; +} #endif #ifdef CONFIG_INET diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index b2db9cd9a73f..4e390cd8f72a 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1314,21 +1314,27 @@ void skb_flow_dissector_init(struct flow_dissector *flow_dissector, unsigned int key_count); struct bpf_flow_dissector; +struct virtio_net_hdr; bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx, - __be16 proto, int nhoff, int hlen, unsigned int flags); + __be16 proto, int nhoff, int hlen, unsigned int flags, + const struct virtio_net_hdr *vhdr, + bool vhdr_is_little_endian); bool __skb_flow_dissect(const struct net *net, const struct sk_buff *skb, struct flow_dissector *flow_dissector, void *target_container, const void *data, - __be16 proto, int nhoff, int hlen, unsigned int flags); + __be16 proto, int nhoff, int hlen, unsigned int flags, + const struct virtio_net_hdr *vhdr, + bool vhdr_is_little_endian); static inline bool skb_flow_dissect(const struct sk_buff *skb, struct flow_dissector *flow_dissector, void *target_container, unsigned int flags) { return __skb_flow_dissect(NULL, skb, flow_dissector, - target_container, NULL, 0, 0, 0, flags); + target_container, NULL, 0, 0, 0, flags, NULL, + false); } static inline bool skb_flow_dissect_flow_keys(const struct sk_buff *skb, @@ -1337,7 +1343,22 @@ static inline bool skb_flow_dissect_flow_keys(const struct sk_buff *skb, { memset(flow, 0, sizeof(*flow)); return __skb_flow_dissect(NULL, skb, &flow_keys_dissector, - flow, NULL, 0, 0, 0, flags); + flow, NULL, 0, 0, 0, flags, NULL, false); +} + +static inline bool +__skb_flow_dissect_flow_keys_basic(const struct net *net, + const struct sk_buff *skb, + struct flow_keys_basic *flow, + const void *data, __be16 proto, + int nhoff, int hlen, unsigned int flags, + const struct virtio_net_hdr *vhdr, + bool vhdr_is_little_endian) +{ + memset(flow, 0, sizeof(*flow)); + return __skb_flow_dissect(net, skb, &flow_keys_basic_dissector, flow, + data, proto, nhoff, hlen, flags, vhdr, + vhdr_is_little_endian); } static inline bool @@ -1347,9 +1368,9 @@ skb_flow_dissect_flow_keys_basic(const struct net *net, const void *data, __be16 proto, int nhoff, int hlen, unsigned int flags) { - memset(flow, 0, sizeof(*flow)); - return __skb_flow_dissect(net, skb, &flow_keys_basic_dissector, flow, - data, proto, nhoff, hlen, flags); + return __skb_flow_dissect_flow_keys_basic(net, skb, flow, data, proto, + nhoff, hlen, flags, NULL, + false); } void skb_flow_dissect_meta(const struct sk_buff *skb, diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 418b9b813d65..0524dec15c6d 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -6017,6 +6017,7 @@ struct bpf_flow_keys { }; __u32 flags; __be32 flow_label; + __bpf_md_ptr(const struct virtio_net_hdr *, vhdr); }; struct bpf_func_info { diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 331b170d9fcc..d4876d5e8959 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -3372,18 +3372,6 @@ static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off, return -EACCES; } -static int check_flow_keys_access(struct bpf_verifier_env *env, int off, - int size) -{ - if (size < 0 || off < 0 || - (u64)off + size > sizeof(struct bpf_flow_keys)) { - verbose(env, "invalid access to flow keys off=%d size=%d\n", - off, size); - return -EACCES; - } - return 0; -} - static int check_sock_access(struct bpf_verifier_env *env, int insn_idx, u32 regno, int off, int size, enum bpf_access_type t) @@ -4210,6 +4198,8 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn if (!err && t == BPF_READ && value_regno >= 0) mark_reg_unknown(env, regs, value_regno); } else if (reg->type == PTR_TO_FLOW_KEYS) { + struct bpf_insn_access_aux info = {}; + if (t == BPF_WRITE && value_regno >= 0 && is_pointer_value(env, value_regno)) { verbose(env, "R%d leaks addr into flow keys\n", @@ -4217,9 +4207,22 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn return -EACCES; } - err = check_flow_keys_access(env, off, size); - if (!err && t == BPF_READ && value_regno >= 0) - mark_reg_unknown(env, regs, value_regno); + err = bpf_flow_keys_is_valid_access(off, size, t, &info); + if (err) { + verbose(env, + "invalid access to flow keys off=%d size=%d\n", + off, size); + } else if (t == BPF_READ && value_regno >= 0) { + if (info.reg_type == PTR_TO_BTF_ID_OR_NULL) { + mark_reg_known_zero(env, regs, value_regno); + regs[value_regno].type = info.reg_type; + regs[value_regno].btf = info.btf; + regs[value_regno].btf_id = info.btf_id; + regs[value_regno].id = ++env->id_gen; + } else { + mark_reg_unknown(env, regs, value_regno); + } + } } else if (type_is_sk_pointer(reg->type)) { if (t == BPF_WRITE) { verbose(env, "R%d cannot write into %s\n", diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c index aa47af349ba8..a11c5ce99ccb 100644 --- a/net/bpf/test_run.c +++ b/net/bpf/test_run.c @@ -797,7 +797,7 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, bpf_test_timer_enter(&t); do { retval = bpf_flow_dissect(prog, &ctx, eth->h_proto, ETH_HLEN, - size, flags); + size, flags, NULL, false); } while (bpf_test_timer_continue(&t, repeat, &ret, &duration)); bpf_test_timer_leave(&t); diff --git a/net/core/filter.c b/net/core/filter.c index 239de1306de9..c3964ef8f387 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -7880,6 +7880,33 @@ static bool sock_filter_is_valid_access(int off, int size, prog->expected_attach_type); } +BTF_ID_LIST_SINGLE(bpf_flow_dissector_btf_ids, struct, virtio_net_hdr); + +int bpf_flow_keys_is_valid_access(int off, int size, enum bpf_access_type t, + struct bpf_insn_access_aux *info) +{ + if (off < 0 || + (u64)off + size > offsetofend(struct bpf_flow_keys, vhdr)) + return -EACCES; + + switch (off) { + case bpf_ctx_range_ptr(struct bpf_flow_keys, vhdr): + if (t == BPF_WRITE || off % size != 0 || size != sizeof(__u64)) + return -EACCES; + + if (!bpf_flow_dissector_btf_ids[0]) + return -EINVAL; + + info->btf = bpf_get_btf_vmlinux(); + info->reg_type = PTR_TO_BTF_ID_OR_NULL; + info->btf_id = bpf_flow_dissector_btf_ids[0]; + + break; + } + + return 0; +} + static int bpf_noop_prologue(struct bpf_insn *insn_buf, bool direct_write, const struct bpf_prog *prog) { @@ -8358,6 +8385,8 @@ static bool flow_dissector_is_valid_access(int off, int size, return false; info->reg_type = PTR_TO_FLOW_KEYS; return true; + case bpf_ctx_range(struct __sk_buff, len): + return size == size_default; default: return false; } @@ -8390,6 +8419,30 @@ static u32 flow_dissector_convert_ctx_access(enum bpf_access_type type, si->dst_reg, si->src_reg, offsetof(struct bpf_flow_dissector, flow_keys)); break; + + case offsetof(struct __sk_buff, len): + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_flow_dissector, skb), + si->dst_reg, si->src_reg, + offsetof(struct bpf_flow_dissector, skb)); + *insn++ = BPF_JMP_IMM(BPF_JNE, si->dst_reg, 0, 4); + /* bpf_flow_dissector->skb == NULL */ + /* dst_reg = bpf_flow_dissector->data_end */ + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_flow_dissector, data_end), + si->dst_reg, si->src_reg, + offsetof(struct bpf_flow_dissector, data_end)); + /* AX = bpf_flow_dissector->data */ + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_flow_dissector, data), + BPF_REG_AX, si->src_reg, + offsetof(struct bpf_flow_dissector, data)); + /* dst_reg -= bpf_flow_dissector->data */ + *insn++ = BPF_ALU64_REG(BPF_SUB, si->dst_reg, BPF_REG_AX); + *insn++ = BPF_JMP_A(1); + /* bpf_flow_dissector->skb != NULL */ + /* bpf_flow_dissector->skb->len */ + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, len), + si->dst_reg, si->dst_reg, + offsetof(struct sk_buff, len)); + break; } return insn - insn_buf; diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 2aadbfc5193b..609e24ba98ea 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -28,6 +28,7 @@ #include <scsi/fc/fc_fcoe.h> #include <uapi/linux/batadv_packet.h> #include <linux/bpf.h> +#include <linux/virtio_net.h> #if IS_ENABLED(CONFIG_NF_CONNTRACK) #include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_labels.h> @@ -864,16 +865,38 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys, } bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx, - __be16 proto, int nhoff, int hlen, unsigned int flags) + __be16 proto, int nhoff, int hlen, unsigned int flags, + const struct virtio_net_hdr *vhdr, + bool vhdr_is_little_endian) { struct bpf_flow_keys *flow_keys = ctx->flow_keys; u32 result; +/* vnet hdr is either machine endian (virtio spec < v1) or le (>= v1) */ +#if defined(__BIG_ENDIAN_BITFIELD) + struct virtio_net_hdr vnet_hdr_local; + + if (vhdr && vhdr_is_little_endian) { + vnet_hdr_local.flags = vhdr->flags; + vnet_hdr_local.gso_type = vhdr->gso_type; + vnet_hdr_local.hdr_len = __virtio16_to_cpu(false, + vhdr->hdr_len); + vnet_hdr_local.gso_size = __virtio16_to_cpu(false, + vhdr->gso_size); + vnet_hdr_local.csum_start = __virtio16_to_cpu(false, + vhdr->csum_start); + vnet_hdr_local.csum_offset = __virtio16_to_cpu(false, + vhdr->csum_offset); + vhdr = &vnet_hdr_local; + } +#endif + /* Pass parameters to the BPF program */ memset(flow_keys, 0, sizeof(*flow_keys)); flow_keys->n_proto = proto; flow_keys->nhoff = nhoff; flow_keys->thoff = flow_keys->nhoff; + flow_keys->vhdr = vhdr; BUILD_BUG_ON((int)BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG != (int)FLOW_DISSECTOR_F_PARSE_1ST_FRAG); @@ -904,6 +927,8 @@ bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx, * @hlen: packet header length, if @data is NULL use skb_headlen(skb) * @flags: flags that control the dissection process, e.g. * FLOW_DISSECTOR_F_STOP_AT_ENCAP. + * @vhdr: virtio_net_header to include in kernel context for BPF flow dissector + * @vhdr_is_little_endian: whether virtio_net_hdr fields are little endian * * The function will try to retrieve individual keys into target specified * by flow_dissector from either the skbuff or a raw buffer specified by the @@ -915,7 +940,9 @@ bool __skb_flow_dissect(const struct net *net, const struct sk_buff *skb, struct flow_dissector *flow_dissector, void *target_container, const void *data, - __be16 proto, int nhoff, int hlen, unsigned int flags) + __be16 proto, int nhoff, int hlen, unsigned int flags, + const struct virtio_net_hdr *vhdr, + bool vhdr_is_little_endian) { struct flow_dissector_key_control *key_control; struct flow_dissector_key_basic *key_basic; @@ -1012,7 +1039,8 @@ bool __skb_flow_dissect(const struct net *net, prog = READ_ONCE(run_array->items[0].prog); ret = bpf_flow_dissect(prog, &ctx, n_proto, nhoff, - hlen, flags); + hlen, flags, vhdr, + vhdr_is_little_endian); __skb_flow_bpf_to_target(&flow_keys, flow_dissector, target_container); rcu_read_unlock(); @@ -1610,7 +1638,7 @@ u32 __skb_get_hash_symmetric(const struct sk_buff *skb) memset(&keys, 0, sizeof(keys)); __skb_flow_dissect(NULL, skb, &flow_keys_dissector_symmetric, &keys, NULL, 0, 0, 0, - FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL); + FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL, NULL, false); return __flow_hash_from_keys(&keys, &hashrnd); } diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 418b9b813d65..0524dec15c6d 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -6017,6 +6017,7 @@ struct bpf_flow_keys { }; __u32 flags; __be32 flow_label; + __bpf_md_ptr(const struct virtio_net_hdr *, vhdr); }; struct bpf_func_info {