From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <adrien.mazarguil@6wind.com>
Received: from mail-wm0-f45.google.com (mail-wm0-f45.google.com [74.125.82.45])
 by dpdk.org (Postfix) with ESMTP id 2904A5694
 for <dev@dpdk.org>; Wed, 16 Nov 2016 17:24:50 +0100 (CET)
Received: by mail-wm0-f45.google.com with SMTP id g23so250235450wme.1
 for <dev@dpdk.org>; Wed, 16 Nov 2016 08:24:50 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=6wind-com.20150623.gappssmtp.com; s=20150623;
 h=from:to:cc:subject:date:message-id:in-reply-to:references;
 bh=a6/O69iGY13qk0WPnfMtGnKQyLVOX2KDMwBv7ffg1Rc=;
 b=o/A0MRpGDCpi6Ky02TvrxtKQjHYtqhTRUlnKtMfBSvoO5z+dTjPmIPWGU2yMNPWNf6
 sFPJemIkMt/xj63KmBtQVzBewk/vtflTg53avTaSUaAempbrAHyvjAwppbpZTqTMwJUH
 oiZF1KznAAh/4vDkPV+2v2rl1fKhqWssT/fL7FIIFi01+Z/I5u4vCIdRcI63EG6GeD+y
 b3wjnmO6ovbVdukdQCgehWtFCHGVMCP2R2e3x5FHmCNaQrywL7SuRwp2J1sWpxGlfa7e
 LrxncFCSXPyZMmPEzJOChvkWfvxgLhB2EUYKcURCN7br2EoqcmrH2gngEGugJ05VtyGw
 Ul1w==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20130820;
 h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to
 :references;
 bh=a6/O69iGY13qk0WPnfMtGnKQyLVOX2KDMwBv7ffg1Rc=;
 b=R31vt0pZnvm7Y/5zPjtMnhlkMpdYBItpBQXxcPGWptHbdaszvGpOhSl7pq31x6a6Zg
 AbvbrCrHGGf7tsx6ZXyXp4aQe6ioVTqpNQHypMcB5iE9wAURKiyK5MhnpAn8t0VwF61k
 vwOS/Jw5u384WNl8y47NJJGBQcYyxfOmY3UiUU39T4ga9H+TAhmIo3GkVX+HKZleTFgp
 yHYyUguqkINsgsST7sHbiY+dc0M7Nirl1gzhsoUmqdCFu+M6B2tpCXL417vYfmHDFcvI
 BwnbcwBtZE4dKeJL1+JzfVP/ERSJVZz5820Hq7jc3diB/0jN2HwMtyXJFv8H/z2ysuKQ
 f85w==
X-Gm-Message-State: ABUngvc2k7kh2SEG3Hm6Zg/cGPiOLIJRWTh/KcXKQ1jCr1CoYrmO0Di99kB3n1EfY2+GRqq0
X-Received: by 10.28.154.86 with SMTP id c83mr10491301wme.23.1479313489818;
 Wed, 16 Nov 2016 08:24:49 -0800 (PST)
Received: from 6wind.com (guy78-3-82-239-227-177.fbx.proxad.net.
 [82.239.227.177])
 by smtp.gmail.com with ESMTPSA id j6sm41305576wjk.25.2016.11.16.08.24.48
 (version=TLS1_2 cipher=AES128-SHA bits=128/128);
 Wed, 16 Nov 2016 08:24:49 -0800 (PST)
From: Adrien Mazarguil <adrien.mazarguil@6wind.com>
To: dev@dpdk.org
Cc: Thomas Monjalon <thomas.monjalon@6wind.com>,
 Pablo de Lara <pablo.de.lara.guarch@intel.com>,
 Olivier Matz <olivier.matz@6wind.com>
Date: Wed, 16 Nov 2016 17:23:44 +0100
Message-Id: <2b768b4a8a90c075efabc4f598e84a7bf11b1592.1479309720.git.adrien.mazarguil@6wind.com>
X-Mailer: git-send-email 2.1.4
In-Reply-To: <cover.1479309719.git.adrien.mazarguil@6wind.com>
References: <cover.1471632644.git.adrien.mazarguil@6wind.com>
 <cover.1479309719.git.adrien.mazarguil@6wind.com>
Subject: [dpdk-dev] [PATCH 18/22] app/testpmd: add items eth/vlan to flow
	command
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: patches and discussions about DPDK <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: Wed, 16 Nov 2016 16:24:50 -0000

These pattern items match basic Ethernet headers (source, destination and
type) and related 802.1Q/ad VLAN headers.

Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
 app/test-pmd/cmdline_flow.c | 126 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 126 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 6f2f26c..f2bd405 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -43,6 +43,7 @@
 #include <rte_ethdev.h>
 #include <rte_byteorder.h>
 #include <cmdline_parse.h>
+#include <cmdline_parse_etheraddr.h>
 #include <rte_flow.h>
 
 #include "testpmd.h"
@@ -59,6 +60,7 @@ enum index {
 	PREFIX,
 	BOOLEAN,
 	STRING,
+	MAC_ADDR,
 	RULE_ID,
 	PORT_ID,
 	GROUP_ID,
@@ -115,6 +117,13 @@ enum index {
 	ITEM_RAW_OFFSET,
 	ITEM_RAW_LIMIT,
 	ITEM_RAW_PATTERN,
+	ITEM_ETH,
+	ITEM_ETH_DST,
+	ITEM_ETH_SRC,
+	ITEM_ETH_TYPE,
+	ITEM_VLAN,
+	ITEM_VLAN_TPID,
+	ITEM_VLAN_TCI,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -239,6 +248,14 @@ struct token {
 		.size = (sz), \
 	})
 
+/** Same as ARGS_ENTRY() using network byte ordering. */
+#define ARGS_ENTRY_HTON(s, f) \
+	(&(const struct arg){ \
+		.hton = 1, \
+		.offset = offsetof(s, f), \
+		.size = sizeof(((s *)0)->f), \
+	})
+
 /** Parser output buffer layout expected by cmd_flow_parsed(). */
 struct buffer {
 	enum index command; /**< Flow command. */
@@ -330,6 +347,8 @@ static const enum index next_item[] = {
 	ITEM_VF,
 	ITEM_PORT,
 	ITEM_RAW,
+	ITEM_ETH,
+	ITEM_VLAN,
 	0,
 };
 
@@ -362,6 +381,21 @@ static const enum index item_raw[] = {
 	0,
 };
 
+static const enum index item_eth[] = {
+	ITEM_ETH_DST,
+	ITEM_ETH_SRC,
+	ITEM_ETH_TYPE,
+	ITEM_NEXT,
+	0,
+};
+
+static const enum index item_vlan[] = {
+	ITEM_VLAN_TPID,
+	ITEM_VLAN_TCI,
+	ITEM_NEXT,
+	0,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -404,6 +438,9 @@ static int parse_boolean(struct context *, const struct token *,
 static int parse_string(struct context *, const struct token *,
 			const char *, unsigned int,
 			void *, unsigned int);
+static int parse_mac_addr(struct context *, const struct token *,
+			  const char *, unsigned int,
+			  void *, unsigned int);
 static int parse_port(struct context *, const struct token *,
 		      const char *, unsigned int,
 		      void *, unsigned int);
@@ -467,6 +504,13 @@ static const struct token token_list[] = {
 		.call = parse_string,
 		.comp = comp_none,
 	},
+	[MAC_ADDR] = {
+		.name = "{MAC address}",
+		.type = "MAC-48",
+		.help = "standard MAC address notation",
+		.call = parse_mac_addr,
+		.comp = comp_none,
+	},
 	[RULE_ID] = {
 		.name = "{rule id}",
 		.type = "RULE ID",
@@ -761,6 +805,50 @@ static const struct token token_list[] = {
 					    pattern,
 					    ITEM_RAW_PATTERN_SIZE)),
 	},
+	[ITEM_ETH] = {
+		.name = "eth",
+		.help = "match Ethernet header",
+		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
+		.next = NEXT(item_eth),
+		.call = parse_vc,
+	},
+	[ITEM_ETH_DST] = {
+		.name = "dst",
+		.help = "destination MAC",
+		.next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_eth, dst)),
+	},
+	[ITEM_ETH_SRC] = {
+		.name = "src",
+		.help = "source MAC",
+		.next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_eth, src)),
+	},
+	[ITEM_ETH_TYPE] = {
+		.name = "type",
+		.help = "EtherType",
+		.next = NEXT(item_eth, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
+	},
+	[ITEM_VLAN] = {
+		.name = "vlan",
+		.help = "match 802.1Q/ad VLAN tag",
+		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
+		.next = NEXT(item_vlan),
+		.call = parse_vc,
+	},
+	[ITEM_VLAN_TPID] = {
+		.name = "tpid",
+		.help = "tag protocol identifier",
+		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tpid)),
+	},
+	[ITEM_VLAN_TCI] = {
+		.name = "tci",
+		.help = "tag control information",
+		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
+	},
 	/* Validate/create actions. */
 	[ACTIONS] = {
 		.name = "actions",
@@ -1394,6 +1482,44 @@ parse_string(struct context *ctx, const struct token *token,
 	return -1;
 }
 
+/**
+ * Parse a MAC address.
+ *
+ * Last argument (ctx->args) is retrieved to determine storage size and
+ * location.
+ */
+static int
+parse_mac_addr(struct context *ctx, const struct token *token,
+	       const char *str, unsigned int len,
+	       void *buf, unsigned int size)
+{
+	const struct arg *arg = pop_args(ctx);
+	struct ether_addr tmp;
+	int ret;
+
+	(void)token;
+	/* Argument is expected. */
+	if (!arg)
+		return -1;
+	size = arg->size;
+	/* Bit-mask fill is not supported. */
+	if (arg->mask || size != sizeof(tmp))
+		goto error;
+	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
+	if (ret < 0 || (unsigned int)ret != len)
+		goto error;
+	if (!ctx->object)
+		return len;
+	buf = (uint8_t *)ctx->object + arg->offset;
+	memcpy(buf, &tmp, size);
+	if (ctx->objmask)
+		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
+	return len;
+error:
+	push_args(ctx, arg);
+	return -1;
+}
+
 /** Boolean values (even indices stand for false). */
 static const char *const boolean_name[] = {
 	"0", "1",
-- 
2.1.4