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

Reply via email to