From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <beilei.xing@intel.com>
Received: from mga14.intel.com (mga14.intel.com [192.55.52.115])
 by dpdk.org (Postfix) with ESMTP id 0D746567A
 for <dev@dpdk.org>; Fri,  2 Dec 2016 05:13:09 +0100 (CET)
Received: from orsmga003.jf.intel.com ([10.7.209.27])
 by fmsmga103.fm.intel.com with ESMTP; 01 Dec 2016 20:13:09 -0800
X-ExtLoop1: 1
X-IronPort-AV: E=Sophos;i="5.33,284,1477983600"; d="scan'208";a="907853527"
Received: from dpdk9.sh.intel.com ([10.239.129.141])
 by orsmga003.jf.intel.com with ESMTP; 01 Dec 2016 20:13:08 -0800
From: Beilei Xing <beilei.xing@intel.com>
To: jingjing.wu@intel.com,
	helin.zhang@intel.com
Cc: dev@dpdk.org,
	wenzhuo.lu@intel.com
Date: Fri,  2 Dec 2016 06:53:31 -0500
Message-Id: <1480679625-4157-11-git-send-email-beilei.xing@intel.com>
X-Mailer: git-send-email 2.5.5
In-Reply-To: <1480679625-4157-1-git-send-email-beilei.xing@intel.com>
References: <1480679625-4157-1-git-send-email-beilei.xing@intel.com>
Subject: [dpdk-dev] [PATCH 10/24] ethdev: parse ethertype filter
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <http://dpdk.org/ml/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://dpdk.org/ml/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <http://dpdk.org/ml/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
X-List-Received-Date: Fri, 02 Dec 2016 04:13:10 -0000

Check if the rule is a ethertype rule, and get the ethertype
info BTW.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
 lib/librte_ether/rte_flow.c        | 136 +++++++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_flow_driver.h |  34 ++++++++++
 2 files changed, 170 insertions(+)

diff --git a/lib/librte_ether/rte_flow.c b/lib/librte_ether/rte_flow.c
index 064963d..acc9057 100644
--- a/lib/librte_ether/rte_flow.c
+++ b/lib/librte_ether/rte_flow.c
@@ -157,3 +157,139 @@ rte_flow_query(uint8_t port_id,
 			   NULL, rte_strerror(ENOTSUP));
 	return -rte_errno;
 }
+
+/**
+ * Parse the rule to see if it is a ethertype rule.
+ * And get the ethertype filter info BTW.
+ */
+int
+cons_parse_ethertype_filter(const struct rte_flow_attr *attr,
+			    const struct rte_flow_item *pattern,
+			    const struct rte_flow_action *actions,
+			    struct rte_eth_ethertype_filter *filter,
+			    struct rte_flow_error *error)
+{
+	const struct rte_flow_item *item;
+	const struct rte_flow_action *act;
+	const struct rte_flow_item_eth *eth_spec;
+	const struct rte_flow_item_eth *eth_mask;
+	const struct rte_flow_action_queue *act_q;
+	uint32_t i, j;
+
+	/************************************************
+	 * parse pattern
+	 ************************************************/
+	i = 0;
+
+	/* The first not void item should be MAC. */
+	PATTERN_SKIP_VOID(filter, struct rte_eth_ethertype_filter,
+			  RTE_FLOW_ERROR_TYPE_ITEM_NUM);
+	if (item->type != RTE_FLOW_ITEM_TYPE_ETH) {
+		error->type = RTE_FLOW_ERROR_TYPE_ITEM;
+		return -EINVAL;
+	}
+
+	/* Get the MAC info. */
+	if (!item->spec || !item->mask) {
+		error->type = RTE_FLOW_ERROR_TYPE_ITEM;
+		return -EINVAL;
+	}
+
+	eth_spec = (const struct rte_flow_item_eth *)item->spec;
+	eth_mask = (const struct rte_flow_item_eth *)item->mask;
+	/**
+	 * Source MAC address must be masked.
+	 * Destination MAC address must be totally masked or not.
+	 */
+	if (eth_mask->src.addr_bytes[0] ||
+	    (eth_mask->dst.addr_bytes[0] != 0xFF &&
+	     eth_mask->dst.addr_bytes[0])) {
+		error->type = RTE_FLOW_ERROR_TYPE_ITEM;
+		return -EINVAL;
+	}
+
+	for (j = 1; j < ETHER_ADDR_LEN; j++) {
+		if (eth_mask->src.addr_bytes[j] !=
+		    eth_mask->src.addr_bytes[0] ||
+		    eth_mask->dst.addr_bytes[j] !=
+		    eth_mask->dst.addr_bytes[0]) {
+			error->type = RTE_FLOW_ERROR_TYPE_ITEM;
+			return -EINVAL;
+		}
+	}
+
+	if ((eth_mask->type & 0xFFFF) != 0xFFFF) {
+		error->type = RTE_FLOW_ERROR_TYPE_ITEM;
+		return -EINVAL;
+	}
+
+	if (eth_mask->dst.addr_bytes[0]) {
+		filter->mac_addr = eth_spec->dst;
+		filter->flags |= RTE_ETHTYPE_FLAGS_MAC;
+	} else {
+		filter->flags &= ~RTE_ETHTYPE_FLAGS_MAC;
+	}
+	filter->ether_type = (uint16_t)eth_spec->type;
+
+	/* Check if the next not void item is END. */
+	i++;
+	PATTERN_SKIP_VOID(filter, struct rte_eth_ethertype_filter,
+			  RTE_FLOW_ERROR_TYPE_ITEM_NUM);
+	if (item->type != RTE_FLOW_ITEM_TYPE_END) {
+		error->type = RTE_FLOW_ERROR_TYPE_ITEM;
+		return -EINVAL;
+	}
+
+	/************************************************
+	 * parse action
+	 ************************************************/
+	i = 0;
+
+	/* Check if the first not void action is QUEUE or DROP. */
+	ACTION_SKIP_VOID(filter, struct rte_eth_ethertype_filter,
+			 RTE_FLOW_ERROR_TYPE_ACTION_NUM);
+	if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE &&
+	    act->type != RTE_FLOW_ACTION_TYPE_DROP) {
+		error->type = RTE_FLOW_ERROR_TYPE_ACTION;
+		return -EINVAL;
+	}
+
+	if (act->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
+		act_q = (const struct rte_flow_action_queue *)act->conf;
+		filter->queue = act_q->index;
+	} else {
+		filter->flags |= RTE_ETHTYPE_FLAGS_DROP;
+	}
+
+	/* Check if the next not void item is END */
+	i++;
+	ACTION_SKIP_VOID(filter, struct rte_eth_ethertype_filter,
+			 RTE_FLOW_ERROR_TYPE_ACTION_NUM);
+	if (act->type != RTE_FLOW_ACTION_TYPE_END) {
+		error->type = RTE_FLOW_ERROR_TYPE_ACTION;
+		return -EINVAL;
+	}
+
+	/************************************************
+	 * parse attr
+	 ************************************************/
+	/* Must be input direction */
+	if (!attr->ingress) {
+		error->type = RTE_FLOW_ERROR_TYPE_ATTR_INGRESS;
+		return -EINVAL;
+	}
+
+	/* Not supported */
+	if (attr->egress) {
+		error->type = RTE_FLOW_ERROR_TYPE_ATTR_EGRESS;
+		return -EINVAL;
+	}
+
+	/* Not supported */
+	if (attr->priority) {
+		error->type = RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY;
+		return -EINVAL;
+	}
+
+	return 0;
+}
diff --git a/lib/librte_ether/rte_flow_driver.h b/lib/librte_ether/rte_flow_driver.h
index a88c621..2760c74 100644
--- a/lib/librte_ether/rte_flow_driver.h
+++ b/lib/librte_ether/rte_flow_driver.h
@@ -170,6 +170,40 @@ rte_flow_error_set(struct rte_flow_error *error,
 const struct rte_flow_ops *
 rte_flow_ops_get(uint8_t port_id, struct rte_flow_error *error);
 
+int cons_parse_ethertype_filter(const struct rte_flow_attr *attr,
+			    const struct rte_flow_item *pattern,
+			    const struct rte_flow_action *actions,
+			    struct rte_eth_ethertype_filter *filter,
+			    struct rte_flow_error *error);
+
+#define PATTERN_SKIP_VOID(filter, filter_struct, error_type)		\
+	do {								\
+		if (!pattern) {						\
+			memset(filter, 0, sizeof(filter_struct));	\
+			error->type = error_type;                       \
+			return -EINVAL;					\
+		}							\
+		item = pattern + i;					\
+		while (item->type == RTE_FLOW_ITEM_TYPE_VOID) {		\
+			i++;						\
+			item = pattern + i;				\
+		}							\
+	} while (0)
+
+#define ACTION_SKIP_VOID(filter, filter_struct, error_type)		\
+	do {								\
+		if (!actions) {						\
+			memset(filter, 0, sizeof(filter_struct));	\
+			error->type = error_type;			\
+			return -EINVAL;					\
+		}							\
+		act = actions + i;					\
+		while (act->type == RTE_FLOW_ACTION_TYPE_VOID) {	\
+			i++;						\
+			act = actions + i;				\
+		}							\
+	} while (0)
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.5.5