DPDK patches and discussions
 help / color / mirror / Atom feed
From: Ophir Munk <ophirmu@mellanox.com>
To: Pascal Mazon <pascal.mazon@6wind.com>
Cc: Ophir Munk <ophirmu@mellanox.com>,
	dev@dpdk.org, Thomas Monjalon <thomas@monjalon.net>,
	Olga Shern <olgas@mellanox.com>
Subject: [dpdk-dev] [PATCH v1 3/3] net/tap: add eBPF classifiers map and actions
Date: Sun, 17 Dec 2017 12:21:55 +0000	[thread overview]
Message-ID: <1513513315-21618-4-git-send-email-ophirmu@mellanox.com> (raw)
In-Reply-To: <1513513315-21618-1-git-send-email-ophirmu@mellanox.com>

Add TC BPF classifier for each TAP queue. Based on this classifier packets
marked with RSS queues will be directed to the matched queue using
TC "skbedit" action. This step is done once at startup

Add RSS BPF map entry for each new RSS rule. The BPF map entry includes
the RSS queues

Add TC BPF actions for each new RSS rule
- Calculate RSS hash based on L2 src, L2 dest, L3 src, L3 dst and L4 src.
- Write the selected RSS queue into skb control block based on the RSS hash
  (i.e. marking the packet) and set the next step as reclassify.

Signed-off-by: Ophir Munk <ophirmu@mellanox.com>
---
 drivers/net/tap/rte_eth_tap.h     |   2 +
 drivers/net/tap/tap_bpf_insns.c   |  55 ++++--
 drivers/net/tap/tap_bpf_program.c |  14 +-
 drivers/net/tap/tap_bpf_shared.h  |  18 +-
 drivers/net/tap/tap_flow.c        | 402 +++++++++++++++++++++++++++++++-------
 5 files changed, 404 insertions(+), 87 deletions(-)

diff --git a/drivers/net/tap/rte_eth_tap.h b/drivers/net/tap/rte_eth_tap.h
index 01ac153..c185473 100644
--- a/drivers/net/tap/rte_eth_tap.h
+++ b/drivers/net/tap/rte_eth_tap.h
@@ -94,6 +94,8 @@ struct pmd_internals {
 	int flower_vlan_support;          /* 1 if kernel supports, else 0 */
 	int rss_enabled;                  /* 1 if RSS is enabled, else 0 */
 	/* implicit rules set when RSS is enabled */
+	int map_fd;                       /* BPF RSS map fd */
+	int bpf_fd[RTE_PMD_TAP_MAX_QUEUES];/* List of bpf fds per queue */
 	LIST_HEAD(tap_rss_flows, rte_flow) rss_flows;
 	LIST_HEAD(tap_flows, rte_flow) flows;        /* rte_flow rules */
 	/* implicit rte_flow rules set when a remote device is active */
diff --git a/drivers/net/tap/tap_bpf_insns.c b/drivers/net/tap/tap_bpf_insns.c
index 951d037..707dce8 100644
--- a/drivers/net/tap/tap_bpf_insns.c
+++ b/drivers/net/tap/tap_bpf_insns.c
@@ -134,7 +134,7 @@ int bpf_load_cls_q_insns(__u32 queue_idx)
 	return bpf_load(BPF_PROG_TYPE_SCHED_ACT,
 		(struct bpf_insn *)cls_q_insns,
 		CLS_Q_INSNS_CNT,
-		"GPL", 0);
+		"Dual BSD/GPL", 0);
 }
 
 /*
@@ -174,7 +174,7 @@ int bpf_load_tailing_insns(void)
 	return bpf_load(BPF_PROG_TYPE_SCHED_ACT,
 		(struct bpf_insn *)tailing_insns,
 		TAILING_INSNS_CNT,
-		"GPL", 0);
+		"Dual BSD/GPL", 0);
 }
 
 /*
@@ -220,7 +220,7 @@ int bpf_load_hash_appending_insns(void)
 	return bpf_load(BPF_PROG_TYPE_SCHED_ACT,
 		(struct bpf_insn *)hash_appending_insns,
 		HASH_APPENDING_INSNS_CNT,
-		"GPL", 0);
+		"Dual BSD/GPL", 0);
 }
 
 /*
@@ -290,14 +290,14 @@ static struct bpf_insn queue_setting_insns[] = {
  * @return
  *   -1 if the BPF program couldn't be loaded. An fd (int) otherwise.
  */
-int bpf_load_queue_setting_insns(__u32 queue_idx)
+int bpf_load_queue_setting_insns(__u32 key_idx)
 {
-	queue_setting_insns[1].imm = queue_idx;
+	queue_setting_insns[1].imm = key_idx;
 
 	return bpf_load(BPF_PROG_TYPE_SCHED_ACT,
 		(struct bpf_insn *)queue_setting_insns,
 		QUEUE_SETTING_INSNS_CNT,
-		"GPL", 0);
+		"Dual BSD/GPL", 0);
 }
 
 /*
@@ -918,7 +918,7 @@ int bpf_load_l2_src_hash_insns(__u32 key_idx)
 	return bpf_load(BPF_PROG_TYPE_SCHED_ACT,
 		(struct bpf_insn *)l2_src_hash_insns,
 		L2_SRC_HASH_INSNS_CNT,
-		"GPL", 0);
+		"Dual BSD/GPL", 0);
 }
 
 /*
@@ -1525,7 +1525,7 @@ int bpf_load_l2_dst_hash_insns(__u32 key_idx)
 	return bpf_load(BPF_PROG_TYPE_SCHED_ACT,
 		(struct bpf_insn *)l2_dst_hash_insns,
 		L2_DST_HASH_INSNS_CNT,
-		"GPL", 0);
+		"Dual BSD/GPL", 0);
 }
 
 /*
@@ -3285,7 +3285,7 @@ int bpf_load_l3_dst_hash_insns(__u32 key_idx)
 	return bpf_load(BPF_PROG_TYPE_SCHED_ACT,
 		(struct bpf_insn *)l3_dst_hash_insns,
 		L3_DST_HASH_INSNS_CNT,
-		"GPL", 0);
+		"Dual BSD/GPL", 0);
 }
 
 /*
@@ -5034,7 +5034,7 @@ int bpf_load_l3_src_hash_insns(__u32 key_idx)
 	return bpf_load(BPF_PROG_TYPE_SCHED_ACT,
 		(struct bpf_insn *)l3_src_hash_insns,
 		L3_SRC_HASH_INSNS_CNT,
-		"GPL", 0);
+		"Dual BSD/GPL", 0);
 }
 
 /*
@@ -5376,7 +5376,7 @@ int bpf_load_l4_src_hash_insns(__u32 key_idx)
 	return bpf_load(BPF_PROG_TYPE_SCHED_ACT,
 		(struct bpf_insn *)l4_src_hash_insns,
 		L4_SRC_HASH_INSNS_CNT,
-		"GPL", 0);
+		"Dual BSD/GPL", 0);
 }
 
 #ifndef __NR_bpf
@@ -5425,3 +5425,36 @@ int bpf_load(enum bpf_prog_type type,
 
 	return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
 }
+
+
+int bpf_map_create(enum bpf_map_type map_type,
+		unsigned int key_size,
+		unsigned int value_size,
+		unsigned int max_entries)
+{
+	union bpf_attr attr;
+
+	bzero(&attr, sizeof(attr));
+	attr.map_type    = map_type;
+	attr.key_size    = key_size;
+	attr.value_size  = value_size;
+	attr.max_entries = max_entries;
+
+	return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
+}
+
+int bpf_map_update_elem(enum bpf_map_type map_type,
+		int fd, void *key, void *value, __u64 flags)
+{
+	union bpf_attr attr;
+
+	bzero(&attr, sizeof(attr));
+
+	attr.map_type = map_type;
+	attr.map_fd = fd;
+	attr.key = ptr_to_u64(key);
+	attr.value = ptr_to_u64(value);
+	attr.flags = flags;
+
+	return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
+}
diff --git a/drivers/net/tap/tap_bpf_program.c b/drivers/net/tap/tap_bpf_program.c
index e1ae0c5..08370bb 100644
--- a/drivers/net/tap/tap_bpf_program.c
+++ b/drivers/net/tap/tap_bpf_program.c
@@ -57,15 +57,15 @@
  */
 #define QUEUE_OFFSET 1
 
-#define INV_KEY_IDX 0xdeadbeef
+#define KEY_IDX 0xdeadbeef
 
 struct vlan_hdr {
 	__be16 proto;
 	__be16 tci;
 };
 
-__section("maps")
-struct bpf_elf_map map_keys = {
+struct bpf_elf_map __section("maps")
+map_keys = {
 	.type           =       BPF_MAP_TYPE_HASH,
 	.id             =       BPF_MAP_ID_KEY,
 	.size_key       =       sizeof(__u32),
@@ -78,10 +78,10 @@ __section("cls_q") int
 match_q(struct __sk_buff *skb)
 {
 	__u32 queue = skb->cb[1];
-	volatile __u32 q = INV_KEY_IDX;
+	volatile __u32 q = KEY_IDX;
 	__u32 match_queue = QUEUE_OFFSET + q;
 
-	/* printt("match_q$i() queue = %d\n", queue); */
+	/* bpf_printk("match_q$i() queue = %d\n", queue); */
 
 	if (queue != match_queue)
 		return TC_ACT_OK;
@@ -120,7 +120,7 @@ hash(struct __sk_buff *skb, enum hash_field f)
 	void *data_end = (void *)(long)skb->data_end;
 	void *data = (void *)(long)skb->data;
 	__u16 proto = (__u16)skb->protocol;
-	__u32 key_idx = INV_KEY_IDX;
+	__u32 key_idx = KEY_IDX;
 	__u32 hash = skb->cb[0];
 	struct rss_key *rsskey;
 	__u64 off = ETH_HLEN;
@@ -303,7 +303,7 @@ append_hash(struct __sk_buff *skb)
 __section("queue_setting") int
 set_queue(struct __sk_buff *skb)
 {
-	__u32 key_idx = INV_KEY_IDX;
+	__u32 key_idx = KEY_IDX;
 	__u64 hash = skb->cb[0];
 	 struct rss_key *rsskey;
 	 __u32 queue = 0;
diff --git a/drivers/net/tap/tap_bpf_shared.h b/drivers/net/tap/tap_bpf_shared.h
index 6895cf4..e7d2ff4 100644
--- a/drivers/net/tap/tap_bpf_shared.h
+++ b/drivers/net/tap/tap_bpf_shared.h
@@ -11,6 +11,16 @@ enum hash_field {
 	HASH_FIELD_L4_SRC,
 };
 
+enum bpf_fd_index {
+	BPF_L2_DST = HASH_FIELD_L2_DST,
+	BPF_L2_SRC = HASH_FIELD_L2_SRC,
+	BPF_L3_SRC = HASH_FIELD_L3_SRC,
+	BPF_L3_DST = HASH_FIELD_L3_DST,
+	BPF_L4_SRC = HASH_FIELD_L4_SRC,
+	BPF_SET_Q,
+	BPF_MAX,
+};
+
 enum {
 	BPF_MAP_ID_KEY,
 	BPF_MAP_ID_SIMPLE,
@@ -27,7 +37,7 @@ struct rss_key {
 int bpf_load_cls_q_insns(__u32 queue_idx);
 int bpf_load_tailing_insns(void);
 int bpf_load_hash_appending_insns(void);
-int bpf_load_queue_setting_insns(__u32 queue_idx);
+int bpf_load_queue_setting_insns(__u32 key_idx);
 int bpf_load_l2_src_hash_insns(__u32 key_idx);
 int bpf_load_l2_dst_hash_insns(__u32 key_idx);
 int bpf_load_l3_dst_hash_insns(__u32 key_idx);
@@ -37,4 +47,10 @@ int bpf_load_l4_src_hash_insns(__u32 key_idx);
 int bpf_load(enum bpf_prog_type type, const struct bpf_insn *insns,
 		size_t insns_cnt, const char *license, __u32 kern_version);
 
+int bpf_map_create(enum bpf_map_type map_type, unsigned int key_size,
+		unsigned int value_size, unsigned int max_entries);
+
+int bpf_map_update_elem(enum bpf_map_type map_type, int fd, void *key,
+		void *value, __u64 flags);
+
 #endif /* __BPF_SHARED__ */
diff --git a/drivers/net/tap/tap_flow.c b/drivers/net/tap/tap_flow.c
index 355f493..ec6ae3c 100644
--- a/drivers/net/tap/tap_flow.c
+++ b/drivers/net/tap/tap_flow.c
@@ -34,6 +34,7 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/queue.h>
+#include <sys/mount.h>
 
 #include <rte_byteorder.h>
 #include <rte_jhash.h>
@@ -87,11 +88,38 @@ enum {
 };
 #endif
 
+enum bpf_rss_key_e {
+	KEY_CMD_GET = 1,
+	KEY_CMD_RELEASE,
+	KEY_CMD_INIT,
+	KEY_CMD_DEINIT,
+};
+
+enum key_status_e {
+	KEY_STAT_UNSPEC,
+	KEY_STAT_USED,
+	KEY_STAT_AVAILABLE,
+};
+
 #define ISOLATE_HANDLE 1
 
+#define MAX_RSS_KEYS 256
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+#define SEC_NAME_CLS_Q "cls_q"
+const char *sec_name[BPF_MAX] = {
+	[BPF_L2_DST] = "L2_DST",
+	[BPF_L2_SRC] = "L2_SRC",
+	[BPF_L3_DST] = "L3_DST",
+	[BPF_L3_SRC] = "L3_SRC",
+	[BPF_L4_SRC] = "L4_SRC",
+	[BPF_SET_Q] = "queue_setting",
+};
+
 struct rte_flow {
 	LIST_ENTRY(rte_flow) next; /* Pointer to the next rte_flow structure */
 	struct rte_flow *remote_flow; /* associated remote flow */
+	int bpf_fd[BPF_MAX]; /* List of bfs fds */
 	struct nlmsg msg;
 };
 
@@ -120,8 +148,9 @@ struct action_data {
 			uint16_t queue;
 		} skbedit;
 		struct bpf {
+			struct tc_act_bpf bpf;
 			int bpf_fd;
-			char *annotation;
+			const char *annotation;
 		} bpf;
 	};
 };
@@ -157,6 +186,9 @@ tap_flow_isolate(struct rte_eth_dev *dev,
 		 struct rte_flow_error *error);
 
 static int rss_enable(struct pmd_internals *pmd);
+static int bpf_rss_key(enum bpf_rss_key_e cmd, __u32 *key_idx);
+static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd,
+		const struct rte_flow_action_rss *rss);
 
 static const struct rte_flow_ops tap_flow_ops = {
 	.validate = tap_flow_validate,
@@ -874,6 +906,9 @@ add_action(struct rte_flow *flow, size_t *act_index, struct action_data *adata)
 		nlattr_add(&msg->nh, TCA_ACT_BPF_NAME,
 			   strlen(adata->bpf.annotation),
 			   adata->bpf.annotation);
+		nlattr_add(&msg->nh, TCA_ACT_BPF_PARMS,
+			   sizeof(adata->bpf.bpf),
+			   &adata->bpf.bpf);
 	} else {
 		return -1;
 	}
@@ -898,7 +933,7 @@ add_actions(struct rte_flow *flow, int nb_actions, struct action_data *data,
 	for (i = 0; i < nb_actions; i++)
 		if (add_action(flow, &act_index, data + i) < 0)
 			return -1;
-	nlattr_nested_finish(msg); /* nested TCA_FLOWER_ACT */
+	nlattr_nested_finish(msg); /* nested TCA_[FLOWER|BPF|...]_ACT */
 	return 0;
 }
 
@@ -1122,9 +1157,13 @@ priv_flow_process(struct pmd_internals *pmd,
 
 			if (action++)
 				goto exit_action_not_supported;
-			if (!pmd->rss_enabled)
+			if (!pmd->rss_enabled) {
 				err = rss_enable(pmd);
-			(void)rss;
+				if (err)
+					goto exit_action_not_supported;
+			}
+			if (rss)
+				err = rss_add_actions(flow, pmd, rss);
 		} else {
 			goto exit_action_not_supported;
 		}
@@ -1645,39 +1684,59 @@ tap_flow_implicit_flush(struct pmd_internals *pmd, struct rte_flow_error *error)
 	return 0;
 }
 
-#define BPF_PROGRAM "tap_bpf_program.o"
-
 /**
  * Enable RSS on tap: create leading TC rules for queuing.
+ *
+ * @param[in, out] pmd
+ *   Pointer to private structure.
+ *
+ * @return -1 if couldn't create map or add rules, 0 otherwise.
  */
 static int rss_enable(struct pmd_internals *pmd)
 {
 	struct rte_flow *rss_flow = NULL;
-	char section[64];
 	struct nlmsg *msg = NULL;
 	/* 4096 is the maximum number of instructions for a BPF program */
-	char annotation[256];
-	int bpf_fd;
+	char annotation[64];
 	int i;
+	int err = 0;
+
+	/*
+	 * At this point file system /sys/fs/bpf must be mounted
+	 * Check for it or mount it programatically
+	 */
+
+	/*
+	 *  Create RSS MAP
+	 */
+
+	err = bpf_rss_key(KEY_CMD_INIT, NULL);
+	if (err < 0) {
+		RTE_LOG(ERR, PMD, "Failed to initialize BPF RSS keys");
+		return -1;
+	}
+
+	pmd->map_fd = bpf_map_create(BPF_MAP_TYPE_HASH,
+				sizeof(__u32), /* key size */
+				sizeof(struct rss_key),
+				MAX_RSS_KEYS);
+	if (pmd->map_fd < 0) {
+		RTE_LOG(ERR, PMD, "Failed to create eBPF map");
+		return -1;
+	}
 
 	/*
 	 * Add a rule per queue to match reclassified packets and direct them to
 	 * the correct queue.
 	 */
 	for (i = 0; i < pmd->dev->data->nb_rx_queues; i++) {
-		struct action_data adata = {
-			.id = "skbedit",
-			.skbedit = {
-				.skbedit = {
-					.action = TC_ACT_PIPE,
-				},
-				.queue = i,
-			},
-		};
-
-		bpf_fd = bpf_load_cls_q_insns(i);
-		if (bpf_fd == -1)
+		pmd->bpf_fd[i] = bpf_load_cls_q_insns(i);
+		if (pmd->bpf_fd[i] < 0) {
+			RTE_LOG(ERR, PMD,
+				"Failed to load eBPF section %s for queue %d",
+				SEC_NAME_CLS_Q, i);
 			return -1;
+		}
 
 		rss_flow = rte_malloc(__func__, sizeof(struct rte_flow), 0);
 		if (!rss_flow) {
@@ -1692,84 +1751,291 @@ static int rss_enable(struct pmd_internals *pmd)
 					    htons(ETH_P_ALL));
 		msg->t.tcm_parent = TC_H_MAKE(MULTIQ_MAJOR_HANDLE, 0);
 		tap_flow_set_handle(rss_flow);
+
 		nlattr_add(&msg->nh, TCA_KIND, sizeof("bpf"), "bpf");
 		if (nlattr_nested_start(msg, TCA_OPTIONS) < 0)
 			return -1;
-		nlattr_add32(&msg->nh, TCA_BPF_FD, bpf_fd);
-		snprintf(annotation, sizeof(annotation), "%s:[%s]",
-			 BPF_PROGRAM, section);
+		nlattr_add32(&msg->nh, TCA_BPF_FD, pmd->bpf_fd[i]);
+		snprintf(annotation, sizeof(annotation), "[%s%d]",
+			SEC_NAME_CLS_Q, i);
 		nlattr_add(&msg->nh, TCA_BPF_NAME, strlen(annotation),
 			   annotation);
+		/* Actions */
+		{
+			struct action_data adata = {
+				.id = "skbedit",
+				.skbedit = {
+					.skbedit = {
+						.action = TC_ACT_PIPE,
+					},
+					.queue = i,
+				},
+			};
+			if (add_actions(rss_flow, 1, &adata, TCA_BPF_ACT) < 0)
+				return -1;
+		}
+		nlattr_nested_finish(msg); /* nested TCA_OPTIONS */
 
-		if (add_actions(rss_flow, 1, &adata, TCA_BPF_ACT) < 0)
-			return -1;
-		nlattr_nested_finish(msg); /* nested TCA_ACT_OPTIONS */
 		/* Netlink message is now ready to be sent */
 		if (nl_send(pmd->nlsk_fd, &msg->nh) < 0)
 			return -1;
-		if (nl_recv_ack(pmd->nlsk_fd) < 0)
-			return -1;
+		err = nl_recv_ack(pmd->nlsk_fd);
+		if (err < 0) {
+			RTE_LOG(ERR, PMD,
+				"Kernel refused TC filter rule creation (%d): %s\n",
+				errno, strerror(errno));
+			return err;
+		}
 		LIST_INSERT_HEAD(&pmd->rss_flows, rss_flow, next);
 	}
 
-	/* Add a rule that adds 4 bytes at packet's end to hold the hash */
-	bpf_fd = bpf_load_tailing_insns();
-	if (bpf_fd == -1)
+	pmd->rss_enabled = 1;
+	return err;
+}
+
+/**
+ * Manage bpf RSS keys repository with operations: init, get, release
+ *
+ * @param[in] cmd
+ *   Command on RSS keys: init, get, release
+ *
+ * @param[in, out] key_idx
+ *   Pointer to RSS Key index (out for get command, in for release command)
+ *
+ * @return -1 if couldn't get, release or init the RSS keys, 0 otherwise.
+ */
+static int bpf_rss_key(enum bpf_rss_key_e cmd, __u32 *key_idx)
+{
+	__u32 i;
+	int err = -1;
+	static __u32 num_used_keys;
+	static __u32 rss_keys[MAX_RSS_KEYS] = {KEY_STAT_UNSPEC};
+	static __u32 rss_keys_initialized;
+
+	switch (cmd) {
+	case KEY_CMD_GET:
+		if (!rss_keys_initialized)
+			break;
+
+		if (num_used_keys == ARRAY_SIZE(rss_keys))
+			break;
+
+		*key_idx = num_used_keys % ARRAY_SIZE(rss_keys);
+		while (rss_keys[*key_idx] == KEY_STAT_USED)
+			*key_idx = (*key_idx + 1) % ARRAY_SIZE(rss_keys);
+		rss_keys[*key_idx] = KEY_STAT_USED;
+		num_used_keys++;
+		err = 0;
+	break;
+
+	case KEY_CMD_RELEASE:
+		if (!rss_keys_initialized)
+			break;
+
+		if (rss_keys[*key_idx] == KEY_STAT_USED) {
+			rss_keys[*key_idx] = KEY_STAT_AVAILABLE;
+			num_used_keys--;
+			err = 0;
+		}
+	break;
+
+	case KEY_CMD_INIT:
+		for (i = 0; i < ARRAY_SIZE(rss_keys); i++)
+			rss_keys[i] = KEY_STAT_AVAILABLE;
+		rss_keys_initialized = 1;
+		num_used_keys = 0;
+		err = 0;
+	break;
+
+	case KEY_CMD_DEINIT:
+		for (i = 0; i < ARRAY_SIZE(rss_keys); i++)
+			rss_keys[i] = KEY_STAT_UNSPEC;
+		rss_keys_initialized = 0;
+		num_used_keys = 0;
+		err = 0;
+	break;
+
+	default:
+		break;
+	}
+
+	return err;
+}
+
+/**
+ * Add RSS hash calculations and queue selection
+ *
+ * @param[in, out] pmd
+ *   Command on RSS keys: init, get, release
+ *
+ * @param[in] rss
+ *   Pointer to RSS flow actions
+ *
+ * @return -1 if couldn't add any action, 0 otherwise.
+ */
+static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd,
+			   const struct rte_flow_action_rss *rss)
+{
+	/* 4096 is the maximum number of instructions for a BPF program */
+	int i;
+	__u32 key_idx;
+	int err;
+
+	struct rss_key rss_entry = {
+		.key = {
+			0x98badcfe, 0x10325476, 0x98badcfe, 0x10325476,
+			0x98badcfe, 0x10325476, 0x98badcfe, 0x10325476,
+			0x98badcfe, 0x10325476, 0x98badcfe, 0x10325476,
+			0x98badcfe, 0x10325476, 0x98badcfe, 0x10325476,
+		},
+		.key_size = 16,
+		.hash_fields =
+		1 << HASH_FIELD_L2_SRC |
+		1 << HASH_FIELD_L2_DST |
+		1 << HASH_FIELD_L3_SRC |
+		1 << HASH_FIELD_L3_DST |
+		1 << HASH_FIELD_L4_SRC,
+		.queues = { 1, 2 },
+		.nb_queues = 2,
+	};
+	/* Get a new map key for a new RSS rule */
+	err = bpf_rss_key(KEY_CMD_GET, &key_idx);
+	if (err)
+		return -1;
+
+	/* Update RSS map entry with queues */
+	rss_entry.nb_queues = rss->num;
+	for (i = 0; i < rss->num; i++)
+		rss_entry.queues[i] = rss->queue[i];
+
+	/* Add this RSS entry to map */
+	err = bpf_map_update_elem(BPF_MAP_TYPE_HASH, pmd->map_fd,
+				&key_idx, &rss_entry, BPF_ANY);
+
+	if (err) {
+		fprintf(stderr, "RSS map entry #%u failed: %s\n", key_idx,
+			strerror(errno));
+		return -1;
+	}
+
+
+	/*
+	 * Load bpf rules to calculate hash for this key_idx
+	 */
+
+	// OMTODO - consider putting the repetitive pattern below within a macro
+	flow->bpf_fd[BPF_L2_DST] =  bpf_load_l2_dst_hash_insns(key_idx);
+	if (flow->bpf_fd[BPF_L2_DST] < 0) {
+		RTE_LOG(ERR, PMD,
+			"Failed to load eBPF section %s", sec_name[BPF_L2_DST]);
 		return -1;
+	}
 
-	snprintf(annotation, sizeof(annotation), "%s:[%s]", BPF_PROGRAM,
-		 section);
-	rss_flow = rte_malloc(__func__, sizeof(struct rte_flow), 0);
-	if (!rss_flow) {
+	flow->bpf_fd[BPF_L2_SRC] = bpf_load_l2_src_hash_insns(key_idx);
+	if (flow->bpf_fd[BPF_L2_SRC] < 0) {
 		RTE_LOG(ERR, PMD,
-			"Cannot allocate memory for rte_flow");
+			"Failed to load eBPF section %s", sec_name[BPF_L2_SRC]);
 		return -1;
 	}
-	msg = &rss_flow->msg;
-	tc_init_msg(msg, pmd->if_index, RTM_NEWTFILTER,
-		    NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE);
-	msg->t.tcm_info =
-		TC_H_MAKE((RTE_PMD_TAP_MAX_QUEUES + PRIORITY_OFFSET) << 16,
-			  htons(ETH_P_ALL));
-	msg->t.tcm_parent = TC_H_MAKE(MULTIQ_MAJOR_HANDLE, 0);
-	tap_flow_set_handle(rss_flow);
-	nlattr_add(&msg->nh, TCA_KIND, sizeof("flower"), "flower");
-	if (nlattr_nested_start(msg, TCA_OPTIONS) < 0)
+
+	flow->bpf_fd[BPF_L3_DST] = bpf_load_l3_dst_hash_insns(key_idx);
+	if (flow->bpf_fd[BPF_L3_DST] < 0) {
+		RTE_LOG(ERR, PMD,
+			"Failed to load eBPF section %s", sec_name[BPF_L3_DST]);
+		return -1;
+	}
+
+	flow->bpf_fd[BPF_L3_SRC] = bpf_load_l3_src_hash_insns(key_idx);
+	if (flow->bpf_fd[BPF_L3_SRC] < 0) {
+		RTE_LOG(ERR, PMD,
+			"Failed to load eBPF section %s", sec_name[BPF_L3_SRC]);
+		return -1;
+	}
+
+	flow->bpf_fd[BPF_L4_SRC] = bpf_load_l4_src_hash_insns(key_idx);
+	if (flow->bpf_fd[BPF_L4_SRC] < 0) {
+		RTE_LOG(ERR, PMD,
+			"Failed to load eBPF section %s", sec_name[BPF_L4_SRC]);
 		return -1;
+	}
 
-	/* no fields for matching: all packets must match */
+	flow->bpf_fd[BPF_SET_Q] = bpf_load_queue_setting_insns(key_idx);
+	if (flow->bpf_fd[BPF_SET_Q] < 0) {
+		RTE_LOG(ERR, PMD,
+			"Failed to load eBPF section %s", sec_name[BPF_SET_Q]);
+		return -1;
+	}
+
+	/* Actions */
 	{
-		/* Actions */
-		struct action_data data[2] = {
-			[0] = {
+		struct action_data adata[] = {
+			{
+				.id = "bpf",
+				.bpf = {
+					.bpf_fd = flow->bpf_fd[BPF_L2_DST],
+					.annotation = sec_name[BPF_L2_DST],
+					.bpf = {
+						.action = TC_ACT_PIPE,
+					},
+				},
+			},
+			{
+				.id = "bpf",
+				.bpf = {
+					.bpf_fd = flow->bpf_fd[BPF_L2_SRC],
+					.annotation = sec_name[BPF_L2_SRC],
+					.bpf = {
+						.action = TC_ACT_PIPE,
+					},
+				},
+			},
+			{
 				.id = "bpf",
 				.bpf = {
-					.bpf_fd = bpf_fd,
-					.annotation = annotation,
+					.bpf_fd = flow->bpf_fd[BPF_L3_SRC],
+					.annotation = sec_name[BPF_L3_SRC],
+					.bpf = {
+						.action = TC_ACT_PIPE,
+					},
 				},
 			},
-			[1] = {
-				.id = "gact",
-				.gact = {
-					/* continue */
-					.action = TC_ACT_UNSPEC,
+			{
+				.id = "bpf",
+				.bpf = {
+					.bpf_fd = flow->bpf_fd[BPF_L3_DST],
+					.annotation = sec_name[BPF_L3_DST],
+					.bpf = {
+						.action = TC_ACT_PIPE,
+					},
+				},
+			},
+			{
+				.id = "bpf",
+				.bpf = {
+					.bpf_fd = flow->bpf_fd[BPF_L4_SRC],
+					.annotation = sec_name[BPF_L4_SRC],
+					.bpf = {
+						.action = TC_ACT_PIPE,
+					},
+				},
+			},
+			{
+				.id = "bpf",
+				.bpf = {
+					.bpf_fd = flow->bpf_fd[BPF_SET_Q],
+					.annotation = sec_name[BPF_SET_Q],
+					.bpf = {
+						.action = TC_ACT_RECLASSIFY,
+					},
 				},
 			},
 		};
 
-		if (add_actions(rss_flow, 2, data, TCA_FLOWER_ACT) < 0)
+		if (add_actions(flow, ARRAY_SIZE(adata), adata,
+			TCA_FLOWER_ACT) < 0)
 			return -1;
 	}
-	nlattr_nested_finish(msg); /* nested TCA_FLOWER_ACT */
-	nlattr_nested_finish(msg); /* nested TCA_OPTIONS */
-	/* Netlink message is now ready to be sent */
-	if (nl_send(pmd->nlsk_fd, &msg->nh) < 0)
-		return -1;
-	if (nl_recv_ack(pmd->nlsk_fd) < 0)
-		return -1;
-	LIST_INSERT_HEAD(&pmd->rss_flows, rss_flow, next);
 
-	pmd->rss_enabled = 1;
 	return 0;
 }
 
-- 
2.7.4

  parent reply	other threads:[~2017-12-17 12:22 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-17 12:21 [dpdk-dev] [PATCH v1 0/3] TAP RSS eBPF cover letter Ophir Munk
2017-12-17 12:21 ` [dpdk-dev] [PATCH v1 1/3] net/tap: add BPF sections for TAP device Ophir Munk
2017-12-17 12:21 ` [dpdk-dev] [PATCH v1 2/3] net/tap: add eBPF instructions Ophir Munk
2017-12-17 12:21 ` Ophir Munk [this message]
2017-12-28 10:09 ` [dpdk-dev] [PATCH v2 0/2] TAP RSS eBPF cover letter Ophir Munk
2017-12-28 10:09   ` [dpdk-dev] [PATCH v2 1/2] net/tap: add eBPF instructions to TAP device Ophir Munk
2017-12-28 10:09   ` [dpdk-dev] [PATCH v2 2/2] net/tap: implement RSS with eBPF classifier and action Ophir Munk
2018-01-10  7:06   ` [dpdk-dev] [PATCH v3 0/2] TAP RSS eBPF cover letter Ophir Munk
2018-01-10  7:06     ` [dpdk-dev] [PATCH v3 1/2] net/tap: add eBPF instructions to TAP device Ophir Munk
2018-01-10  9:34       ` Pascal Mazon
2018-01-10 10:12         ` Ophir Munk
2018-01-10  7:06     ` [dpdk-dev] [PATCH v3 2/2] net/tap: implement RSS with eBPF classifier and action Ophir Munk
2018-01-10 10:19       ` Pascal Mazon
2018-01-11 17:20         ` Ophir Munk
2018-01-10 10:10     ` [dpdk-dev] [PATCH v3 0/2] TAP RSS eBPF cover letter Jason Wang
2018-01-10 15:34       ` Ophir Munk
2018-01-11  2:45         ` Jason Wang
2018-01-11 17:45     ` [dpdk-dev] [PATCH v4 0/5] " Ophir Munk
2018-01-11 17:45       ` [dpdk-dev] [PATCH v4 1/5] net/tap: support actions for different classifiers Ophir Munk
2018-01-11 17:45       ` [dpdk-dev] [PATCH v4 2/5] net/tap: add eBPF bytes code Ophir Munk
2018-01-11 17:45       ` [dpdk-dev] [PATCH v4 3/5] net/tap: add eBPF program file Ophir Munk
2018-01-11 17:45       ` [dpdk-dev] [PATCH v4 4/5] net/tap: add eBPF API Ophir Munk
2018-01-11 17:45       ` [dpdk-dev] [PATCH v4 5/5] net/tap: implement TAP RSS using eBPF Ophir Munk
2018-01-18 13:38       ` [dpdk-dev] [PATCH v5 0/6] TAP RSS eBPF cover letter Ophir Munk
2018-01-18 13:38         ` [dpdk-dev] [PATCH v5 1/6] net/tap: support actions for different classifiers Ophir Munk
2018-01-18 13:38         ` [dpdk-dev] [PATCH v5 2/6] net/tap: add eBPF bytes code Ophir Munk
2018-01-18 13:38         ` [dpdk-dev] [PATCH v5 3/6] net/tap: add eBPF program file Ophir Munk
2018-01-18 13:38         ` [dpdk-dev] [PATCH v5 4/6] net/tap: add eBPF API Ophir Munk
2018-01-18 13:38         ` [dpdk-dev] [PATCH v5 5/6] net/tap: implement TAP RSS using eBPF Ophir Munk
2018-01-18 13:38         ` [dpdk-dev] [PATCH v5 6/6] doc: detail new tap RSS feature in guides Ophir Munk
2018-01-19  6:48         ` [dpdk-dev] [PATCH v5 0/6] TAP RSS eBPF cover letter Pascal Mazon
2018-01-20 16:15           ` Ferruh Yigit
2018-01-20 21:25             ` Ophir Munk
2018-01-21 14:20               ` Ferruh Yigit
2018-01-20 21:11         ` [dpdk-dev] [PATCH v6 " Ophir Munk
2018-01-20 21:11           ` [dpdk-dev] [PATCH v6 1/6] net/tap: support actions for different classifiers Ophir Munk
2018-01-20 21:11           ` [dpdk-dev] [PATCH v6 2/6] net/tap: add eBPF program file Ophir Munk
2018-01-20 21:11           ` [dpdk-dev] [PATCH v6 3/6] net/tap: add eBPF bytes code Ophir Munk
2018-01-20 21:11           ` [dpdk-dev] [PATCH v6 4/6] net/tap: add eBPF API Ophir Munk
2018-01-20 21:11           ` [dpdk-dev] [PATCH v6 5/6] net/tap: implement TAP RSS using eBPF Ophir Munk
2018-01-20 21:11           ` [dpdk-dev] [PATCH v6 6/6] doc: detail new tap RSS feature in guides Ophir Munk
2018-01-21 14:50           ` [dpdk-dev] [PATCH v6 0/6] TAP RSS eBPF cover letter Ferruh Yigit

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1513513315-21618-4-git-send-email-ophirmu@mellanox.com \
    --to=ophirmu@mellanox.com \
    --cc=dev@dpdk.org \
    --cc=olgas@mellanox.com \
    --cc=pascal.mazon@6wind.com \
    --cc=thomas@monjalon.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).