[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20190813120558.6151-6-toshiaki.makita1@gmail.com>
Date: Tue, 13 Aug 2019 21:05:49 +0900
From: Toshiaki Makita <toshiaki.makita1@...il.com>
To: Alexei Starovoitov <ast@...nel.org>,
Daniel Borkmann <daniel@...earbox.net>,
Martin KaFai Lau <kafai@...com>,
Song Liu <songliubraving@...com>, Yonghong Song <yhs@...com>,
"David S. Miller" <davem@...emloft.net>,
Jakub Kicinski <jakub.kicinski@...ronome.com>,
Jesper Dangaard Brouer <hawk@...nel.org>,
John Fastabend <john.fastabend@...il.com>,
Jamal Hadi Salim <jhs@...atatu.com>,
Cong Wang <xiyou.wangcong@...il.com>,
Jiri Pirko <jiri@...nulli.us>
Cc: Toshiaki Makita <toshiaki.makita1@...il.com>,
netdev@...r.kernel.org, bpf@...r.kernel.org,
William Tu <u9012063@...il.com>
Subject: [RFC PATCH bpf-next 05/14] xdp_flow: Prepare flow tables in bpf
Add maps for flow tables in bpf. TC flower has hash tables for each flow
mask ordered by priority. To do the same thing, prepare
hashmap-in-arraymap. As bpf does not provide ordered list, we emulate it
by an array. Each array entry has one-byte next index field to implement
a list. Also prepare a one-element array to point to the head index of
the list.
Because of the limitation of bpf maps, the outer array is implemented
using two array maps. "flow_masks" is the array to emulate the list and
its entries have the priority and mask of each flow table. For each
priority/mask, the same index entry of another map "flow_tables", which
is the hashmap-in-arraymap, points to the actual flow table.
The flow insertion logic in UMH and lookup logic in BPF will be
implemented in the following commits.
NOTE: This list emulation by array may be able to be realized by adding
ordered-list type map. In that case we also need map iteration API for
bpf progs.
Signed-off-by: Toshiaki Makita <toshiaki.makita1@...il.com>
---
net/xdp_flow/umh_bpf.h | 18 +++++++++++
net/xdp_flow/xdp_flow_kern_bpf.c | 22 +++++++++++++
net/xdp_flow/xdp_flow_umh.c | 70 ++++++++++++++++++++++++++++++++++++++--
3 files changed, 108 insertions(+), 2 deletions(-)
create mode 100644 net/xdp_flow/umh_bpf.h
diff --git a/net/xdp_flow/umh_bpf.h b/net/xdp_flow/umh_bpf.h
new file mode 100644
index 0000000..b4fe0c6
--- /dev/null
+++ b/net/xdp_flow/umh_bpf.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _NET_XDP_FLOW_UMH_BPF_H
+#define _NET_XDP_FLOW_UMH_BPF_H
+
+#include "msgfmt.h"
+
+#define MAX_FLOWS 1024
+#define MAX_FLOW_MASKS 255
+#define FLOW_MASKS_TAIL 255
+
+struct xdp_flow_mask_entry {
+ struct xdp_flow_key mask;
+ __u16 priority;
+ short count;
+ int next;
+};
+
+#endif
diff --git a/net/xdp_flow/xdp_flow_kern_bpf.c b/net/xdp_flow/xdp_flow_kern_bpf.c
index 74cdb1d..c101156 100644
--- a/net/xdp_flow/xdp_flow_kern_bpf.c
+++ b/net/xdp_flow/xdp_flow_kern_bpf.c
@@ -2,6 +2,28 @@
#define KBUILD_MODNAME "foo"
#include <uapi/linux/bpf.h>
#include <bpf_helpers.h>
+#include "umh_bpf.h"
+
+struct bpf_map_def SEC("maps") flow_masks_head = {
+ .type = BPF_MAP_TYPE_ARRAY,
+ .key_size = sizeof(u32),
+ .value_size = sizeof(int),
+ .max_entries = 1,
+};
+
+struct bpf_map_def SEC("maps") flow_masks = {
+ .type = BPF_MAP_TYPE_ARRAY,
+ .key_size = sizeof(u32),
+ .value_size = sizeof(struct xdp_flow_mask_entry),
+ .max_entries = MAX_FLOW_MASKS,
+};
+
+struct bpf_map_def SEC("maps") flow_tables = {
+ .type = BPF_MAP_TYPE_ARRAY_OF_MAPS,
+ .key_size = sizeof(u32),
+ .value_size = sizeof(u32),
+ .max_entries = MAX_FLOW_MASKS,
+};
SEC("xdp_flow")
int xdp_flow_prog(struct xdp_md *ctx)
diff --git a/net/xdp_flow/xdp_flow_umh.c b/net/xdp_flow/xdp_flow_umh.c
index 734db00..e35666a 100644
--- a/net/xdp_flow/xdp_flow_umh.c
+++ b/net/xdp_flow/xdp_flow_umh.c
@@ -13,7 +13,7 @@
#include <sys/resource.h>
#include <linux/hashtable.h>
#include <linux/err.h>
-#include "msgfmt.h"
+#include "umh_bpf.h"
extern char xdp_flow_bpf_start;
extern char xdp_flow_bpf_end;
@@ -95,11 +95,13 @@ static int setup(void)
static int load_bpf(int ifindex, struct bpf_object **objp)
{
+ int prog_fd, flow_tables_fd, flow_meta_fd, flow_masks_head_fd, err;
+ struct bpf_map *flow_tables, *flow_masks_head;
+ int zero = 0, flow_masks_tail = FLOW_MASKS_TAIL;
struct bpf_object_open_attr attr = {};
char path[256], errbuf[ERRBUF_SIZE];
struct bpf_program *prog;
struct bpf_object *obj;
- int prog_fd, err;
ssize_t len;
len = snprintf(path, 256, "/proc/self/fd/%d", progfile_fd);
@@ -127,6 +129,48 @@ static int load_bpf(int ifindex, struct bpf_object **objp)
bpf_object__for_each_program(prog, obj)
bpf_program__set_type(prog, attr.prog_type);
+ flow_meta_fd = bpf_create_map(BPF_MAP_TYPE_HASH,
+ sizeof(struct xdp_flow_key),
+ sizeof(struct xdp_flow_actions),
+ MAX_FLOWS, 0);
+ if (flow_meta_fd < 0) {
+ err = -errno;
+ pr_err("map creation for flow_tables meta failed: %s\n",
+ strerror(errno));
+ goto err;
+ }
+
+ flow_tables_fd = bpf_create_map_in_map(BPF_MAP_TYPE_ARRAY_OF_MAPS,
+ "flow_tables", sizeof(__u32),
+ flow_meta_fd, MAX_FLOW_MASKS, 0);
+ if (flow_tables_fd < 0) {
+ err = -errno;
+ pr_err("map creation for flow_tables failed: %s\n",
+ strerror(errno));
+ close(flow_meta_fd);
+ goto err;
+ }
+
+ close(flow_meta_fd);
+
+ flow_tables = bpf_object__find_map_by_name(obj, "flow_tables");
+ if (!flow_tables) {
+ pr_err("Cannot find flow_tables\n");
+ err = -ENOENT;
+ close(flow_tables_fd);
+ goto err;
+ }
+
+ err = bpf_map__reuse_fd(flow_tables, flow_tables_fd);
+ if (err) {
+ err = libbpf_err(err, errbuf);
+ pr_err("Failed to reuse flow_tables fd: %s\n", errbuf);
+ close(flow_tables_fd);
+ goto err;
+ }
+
+ close(flow_tables_fd);
+
err = bpf_object__load(obj);
if (err) {
err = libbpf_err(err, errbuf);
@@ -134,6 +178,28 @@ static int load_bpf(int ifindex, struct bpf_object **objp)
goto err;
}
+ flow_masks_head = bpf_object__find_map_by_name(obj, "flow_masks_head");
+ if (!flow_masks_head) {
+ pr_err("Cannot find flow_masks_head map\n");
+ err = -ENOENT;
+ goto err;
+ }
+
+ flow_masks_head_fd = bpf_map__fd(flow_masks_head);
+ if (flow_masks_head_fd < 0) {
+ err = libbpf_err(flow_masks_head_fd, errbuf);
+ pr_err("Invalid flow_masks_head fd: %s\n", errbuf);
+ goto err;
+ }
+
+ if (bpf_map_update_elem(flow_masks_head_fd, &zero, &flow_masks_tail,
+ 0)) {
+ err = -errno;
+ pr_err("Failed to initialize flow_masks_head: %s\n",
+ strerror(errno));
+ goto err;
+ }
+
prog = bpf_object__find_program_by_title(obj, "xdp_flow");
if (!prog) {
pr_err("Cannot find xdp_flow program\n");
--
1.8.3.1
Powered by blists - more mailing lists