Add a new program type for openvswitch. Implements the BPF verifier for the new type.
Signed-off-by: Andy Zhou <az...@nicira.com> --- include/linux/bpf.h | 2 +- include/uapi/linux/bpf.h | 1 + include/uapi/linux/openvswitch.h | 29 +++++++++++++- net/Makefile | 4 +- net/openvswitch/Makefile | 2 + net/openvswitch/bpf.c | 87 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 net/openvswitch/bpf.c diff --git a/include/linux/bpf.h b/include/linux/bpf.h index bbfceb7..2e71cc2 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -99,7 +99,7 @@ enum bpf_access_type { struct bpf_verifier_ops { /* return eBPF function prototype for verification */ - const struct bpf_func_proto *(*get_func_proto)(enum bpf_func_id func_id); + const struct bpf_func_proto *(*get_func_proto)(int func_id); /* return true if 'size' wide access at offset 'off' within bpf_context * with 'type' (read or write) is allowed diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 45da7ec..a9a6b24 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -118,6 +118,7 @@ enum bpf_map_type { enum bpf_prog_type { BPF_PROG_TYPE_UNSPEC, BPF_PROG_TYPE_SOCKET_FILTER, + BPF_PROG_TYPE_OPENVSWITCH, }; /* flags for BPF_MAP_UPDATE_ELEM command */ diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h index 7a8785a..929999c 100644 --- a/include/uapi/linux/openvswitch.h +++ b/include/uapi/linux/openvswitch.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2007-2013 Nicira, Inc. + * Copyright (c) 2007-2015 Nicira, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public @@ -569,6 +569,17 @@ struct ovs_action_push_vlan { __be16 vlan_tci; /* 802.1Q TCI (VLAN ID and priority). */ }; +/** + * struct ovs_action_bpf_prog - %OVS_ACTION_ATTR_BPF_PROG action argument. + * + * XXX The argument size is fixed for now. + */ +struct ovs_action_bpf_prog { + __be32 prog_fd; + __be32 arg0; + __be32 arg1; +}; + /* Data path hash algorithm for computing Datapath hash. * * The algorithm type only specifies the fields in a flow @@ -631,10 +642,26 @@ enum ovs_action_attr { OVS_ACTION_ATTR_HASH, /* struct ovs_action_hash. */ OVS_ACTION_ATTR_PUSH_MPLS, /* struct ovs_action_push_mpls. */ OVS_ACTION_ATTR_POP_MPLS, /* __be16 ethertype. */ + OVS_ACTION_ATTR_SET_MASKED, /* place holder */ + OVS_ACTION_ATTR_BPF_PROG, /* strcut ovs_action_bpf_prog */ __OVS_ACTION_ATTR_MAX }; #define OVS_ACTION_ATTR_MAX (__OVS_ACTION_ATTR_MAX - 1) +/* integer value in 'imm' field of BPF_CALL instruction selects which OVS helper + * function eBPF program intends to call + */ +enum ovs_bpf_func_id { + OVS_BPF_FUNC_unspec, + OVS_BPF_FUNC_output, /* int ovs_bpf_output(ctxt) */ + __OVS_BPF_FUNC_MAX_ID, +}; + +struct ovs_bpf_action_ctxt { + void *skb; + u32 arg0; + u32 arg1; +}; #endif /* _LINUX_OPENVSWITCH_H */ diff --git a/net/Makefile b/net/Makefile index 38704bd..7e92dea 100644 --- a/net/Makefile +++ b/net/Makefile @@ -67,7 +67,9 @@ obj-$(CONFIG_DNS_RESOLVER) += dns_resolver/ obj-$(CONFIG_CEPH_LIB) += ceph/ obj-$(CONFIG_BATMAN_ADV) += batman-adv/ obj-$(CONFIG_NFC) += nfc/ -obj-$(CONFIG_OPENVSWITCH) += openvswitch/ +ifneq ($(CONFIG_OPENVSWITCH),) +obj-y += openvswitch/ +endif obj-$(CONFIG_VSOCKETS) += vmw_vsock/ obj-$(CONFIG_NET_MPLS_GSO) += mpls/ obj-$(CONFIG_HSR) += hsr/ diff --git a/net/openvswitch/Makefile b/net/openvswitch/Makefile index 91b9478..5a3a2b7 100644 --- a/net/openvswitch/Makefile +++ b/net/openvswitch/Makefile @@ -18,3 +18,5 @@ openvswitch-y := \ obj-$(CONFIG_OPENVSWITCH_GENEVE)+= vport-geneve.o obj-$(CONFIG_OPENVSWITCH_VXLAN) += vport-vxlan.o obj-$(CONFIG_OPENVSWITCH_GRE) += vport-gre.o + +obj-y += bpf.o diff --git a/net/openvswitch/bpf.c b/net/openvswitch/bpf.c new file mode 100644 index 0000000..8a33e93 --- /dev/null +++ b/net/openvswitch/bpf.c @@ -0,0 +1,87 @@ +/* Copyright (c) 2015 Nicira Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + */ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/err.h> +#include <linux/bpf.h> +#include <linux/openvswitch.h> +#include <linux/skbuff.h> + +static u64 bpf_helper_output(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) +{ + struct sk_buff *skb = (struct sk_buff *) (unsigned long) r1; + uint32_t port = (uint32_t) (unsigned long) r2; + + printk("helper output %p to port %d\n", skb, port); + return 0; +} + +struct bpf_func_proto bpf_helper_output_proto = { + .func = bpf_helper_output, + .gpl_only = true, + .ret_type = RET_INTEGER, + .arg1_type = ARG_ANYTHING, /* XXX from context */ + .arg2_type = ARG_ANYTHING, + .arg3_type = ARG_ANYTHING, + .arg4_type = ARG_ANYTHING, +}; + +#define BPF_CONTEXT_ACCESS(CTXT, FIELD, RW) \ + [offsetof(struct CTXT, FIELD)] = { \ + FIELD_SIZEOF(struct CTXT, FIELD), \ + RW \ + } + +static const struct bpf_func_proto *ovs_func_proto(int func_id) +{ + switch (func_id) { + case OVS_BPF_FUNC_output: + return &bpf_helper_output_proto; + default: + return NULL; + } +} + +static const struct bpf_context_access { + int size; + enum bpf_access_type type; +} bpf_ctx_access[] = { + BPF_CONTEXT_ACCESS(ovs_bpf_action_ctxt, skb, BPF_READ), + BPF_CONTEXT_ACCESS(ovs_bpf_action_ctxt, arg0, BPF_READ), + BPF_CONTEXT_ACCESS(ovs_bpf_action_ctxt, arg1, BPF_READ) +}; + +static bool test_is_valid_access(int off, int size, enum bpf_access_type type) +{ + const struct bpf_context_access *access; + + if (off < 0 || off >= ARRAY_SIZE(bpf_ctx_access)) + return false; + + access = &bpf_ctx_access[off]; + if (access->size == size && (access->type & type)) + return true; + + return false; +} + +static struct bpf_verifier_ops ovs_bpf_ops = { + .get_func_proto = ovs_func_proto, + .is_valid_access = test_is_valid_access, +}; + +static struct bpf_prog_type_list tl_prog = { + .ops = &ovs_bpf_ops, + .type = BPF_PROG_TYPE_OPENVSWITCH, +}; + +static int __init register_ovs_bpf_ops(void) +{ + bpf_register_prog_type(&tl_prog); + return 0; +} +late_initcall(register_ovs_bpf_ops); -- 1.9.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev