netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/4] cxgb4: add support to offload tc flower
@ 2017-09-21  7:33 Rahul Lakkireddy
  2017-09-21  7:33 ` [PATCH net-next 1/4] cxgb4: add tc flower offload skeleton Rahul Lakkireddy
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Rahul Lakkireddy @ 2017-09-21  7:33 UTC (permalink / raw)
  To: netdev; +Cc: davem, kumaras, ganeshgr, nirranjan, indranil, Rahul Lakkireddy

This series of patches add support to offload tc flower onto Chelsio
NICs.

Patch 1 adds basic skeleton to prepare for offloading tc flower flows.

Patch 2 adds support to add/remove flows for offload.  Flows can have
accompanying masks.  Following match and action are currently supported
for offload:
Match:  ether-protocol, IPv4/IPv6 addresses, L4 ports (TCP/UDP)
Action: drop, redirect to another port on the device.

Patch 3 adds support to offload tc-flower flows having
vlan actions: pop, push, and modify.

Patch 4 adds support to fetch stats for the offloaded tc flower flows
from hardware.

Support for offloading more match and action types are to be followed
in subsequent series.

Thanks,
Rahul

Kumar Sanghvi (4):
  cxgb4: add tc flower offload skeleton
  cxgb4: add basic tc flower offload support
  cxgb4: add support to offload action vlan
  cxgb4: fetch stats for offloaded tc flower flows

 drivers/net/ethernet/chelsio/cxgb4/Makefile        |   4 +-
 drivers/net/ethernet/chelsio/cxgb4/cxgb4.h         |   4 +
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c  | 102 +++++
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c    |  25 ++
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c   | 458 +++++++++++++++++++++
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h   |  66 +++
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h     |   3 +
 7 files changed, 661 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
 create mode 100644 drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h

-- 
2.14.1

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH net-next 1/4] cxgb4: add tc flower offload skeleton
  2017-09-21  7:33 [PATCH net-next 0/4] cxgb4: add support to offload tc flower Rahul Lakkireddy
@ 2017-09-21  7:33 ` Rahul Lakkireddy
  2017-09-21  7:33 ` [PATCH net-next 2/4] cxgb4: add basic tc flower offload support Rahul Lakkireddy
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Rahul Lakkireddy @ 2017-09-21  7:33 UTC (permalink / raw)
  To: netdev; +Cc: davem, kumaras, ganeshgr, nirranjan, indranil, Rahul Lakkireddy

From: Kumar Sanghvi <kumaras@chelsio.com>

Add basic skeleton to prepare for offloading tc-flower flows.

Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
---
 drivers/net/ethernet/chelsio/cxgb4/Makefile        |  4 +-
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c    | 22 +++++++++
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c   | 57 ++++++++++++++++++++++
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h   | 46 +++++++++++++++++
 4 files changed, 128 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
 create mode 100644 drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h

diff --git a/drivers/net/ethernet/chelsio/cxgb4/Makefile b/drivers/net/ethernet/chelsio/cxgb4/Makefile
index 817212702f0a..fecd7aab673b 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/Makefile
+++ b/drivers/net/ethernet/chelsio/cxgb4/Makefile
@@ -4,7 +4,9 @@
 
 obj-$(CONFIG_CHELSIO_T4) += cxgb4.o
 
-cxgb4-objs := cxgb4_main.o l2t.o t4_hw.o sge.o clip_tbl.o cxgb4_ethtool.o cxgb4_uld.o sched.o cxgb4_filter.o cxgb4_tc_u32.o cxgb4_ptp.o
+cxgb4-objs := cxgb4_main.o l2t.o t4_hw.o sge.o clip_tbl.o cxgb4_ethtool.o \
+	      cxgb4_uld.o sched.o cxgb4_filter.o cxgb4_tc_u32.o \
+	      cxgb4_ptp.o cxgb4_tc_flower.o
 cxgb4-$(CONFIG_CHELSIO_T4_DCB) +=  cxgb4_dcb.o
 cxgb4-$(CONFIG_CHELSIO_T4_FCOE) +=  cxgb4_fcoe.o
 cxgb4-$(CONFIG_DEBUG_FS) += cxgb4_debugfs.o
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 92d9d795d874..8923affbdaf8 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -79,6 +79,7 @@
 #include "l2t.h"
 #include "sched.h"
 #include "cxgb4_tc_u32.h"
+#include "cxgb4_tc_flower.h"
 #include "cxgb4_ptp.h"
 
 char cxgb4_driver_name[] = KBUILD_MODNAME;
@@ -2873,6 +2874,25 @@ static int cxgb_set_tx_maxrate(struct net_device *dev, int index, u32 rate)
 	return err;
 }
 
+static int cxgb_setup_tc_flower(struct net_device *dev,
+				struct tc_cls_flower_offload *cls_flower)
+{
+	if (!is_classid_clsact_ingress(cls_flower->common.classid) ||
+	    cls_flower->common.chain_index)
+		return -EOPNOTSUPP;
+
+	switch (cls_flower->command) {
+	case TC_CLSFLOWER_REPLACE:
+		return cxgb4_tc_flower_replace(dev, cls_flower);
+	case TC_CLSFLOWER_DESTROY:
+		return cxgb4_tc_flower_destroy(dev, cls_flower);
+	case TC_CLSFLOWER_STATS:
+		return cxgb4_tc_flower_stats(dev, cls_flower);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static int cxgb_setup_tc_cls_u32(struct net_device *dev,
 				 struct tc_cls_u32_offload *cls_u32)
 {
@@ -2907,6 +2927,8 @@ static int cxgb_setup_tc(struct net_device *dev, enum tc_setup_type type,
 	switch (type) {
 	case TC_SETUP_CLSU32:
 		return cxgb_setup_tc_cls_u32(dev, type_data);
+	case TC_SETUP_CLSFLOWER:
+		return cxgb_setup_tc_flower(dev, type_data);
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
new file mode 100644
index 000000000000..16dff71e4d02
--- /dev/null
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the Chelsio T4/T5/T6 Ethernet driver for Linux.
+ *
+ * Copyright (c) 2017 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <net/tc_act/tc_gact.h>
+#include <net/tc_act/tc_mirred.h>
+
+#include "cxgb4.h"
+#include "cxgb4_tc_flower.h"
+
+int cxgb4_tc_flower_replace(struct net_device *dev,
+			    struct tc_cls_flower_offload *cls)
+{
+	return -EOPNOTSUPP;
+}
+
+int cxgb4_tc_flower_destroy(struct net_device *dev,
+			    struct tc_cls_flower_offload *cls)
+{
+	return -EOPNOTSUPP;
+}
+
+int cxgb4_tc_flower_stats(struct net_device *dev,
+			  struct tc_cls_flower_offload *cls)
+{
+	return -EOPNOTSUPP;
+}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
new file mode 100644
index 000000000000..b321fc205b5a
--- /dev/null
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the Chelsio T4/T5/T6 Ethernet driver for Linux.
+ *
+ * Copyright (c) 2017 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CXGB4_TC_FLOWER_H
+#define __CXGB4_TC_FLOWER_H
+
+#include <net/pkt_cls.h>
+
+int cxgb4_tc_flower_replace(struct net_device *dev,
+			    struct tc_cls_flower_offload *cls);
+int cxgb4_tc_flower_destroy(struct net_device *dev,
+			    struct tc_cls_flower_offload *cls);
+int cxgb4_tc_flower_stats(struct net_device *dev,
+			  struct tc_cls_flower_offload *cls);
+#endif /* __CXGB4_TC_FLOWER_H */
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH net-next 2/4] cxgb4: add basic tc flower offload support
  2017-09-21  7:33 [PATCH net-next 0/4] cxgb4: add support to offload tc flower Rahul Lakkireddy
  2017-09-21  7:33 ` [PATCH net-next 1/4] cxgb4: add tc flower offload skeleton Rahul Lakkireddy
@ 2017-09-21  7:33 ` Rahul Lakkireddy
  2017-09-21 10:55   ` Yunsheng Lin
  2017-09-21  7:33 ` [PATCH net-next 3/4] cxgb4: add support to offload action vlan Rahul Lakkireddy
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Rahul Lakkireddy @ 2017-09-21  7:33 UTC (permalink / raw)
  To: netdev; +Cc: davem, kumaras, ganeshgr, nirranjan, indranil, Rahul Lakkireddy

From: Kumar Sanghvi <kumaras@chelsio.com>

Add support to add/remove flows for offload.  Following match
and action are supported for offloading a flow:

Match: ether-protocol, IPv4/IPv6 addresses, L4 ports (TCP/UDP)
Action: drop, redirect to another port on the device.

The qualifying flows can have accompanying mask information.

Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
---
 drivers/net/ethernet/chelsio/cxgb4/cxgb4.h         |   3 +
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c  |  26 ++
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c    |   2 +
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c   | 285 ++++++++++++++++++++-
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h   |  17 ++
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h     |   1 +
 6 files changed, 332 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index ea72d2d2e1b4..26eac599ab2c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -904,6 +904,9 @@ struct adapter {
 	/* TC u32 offload */
 	struct cxgb4_tc_u32_table *tc_u32;
 	struct chcr_stats_debug chcr_stats;
+
+	/* TC flower offload */
+	DECLARE_HASHTABLE(flower_anymatch_tbl, 9);
 };
 
 /* Support for "sched-class" command to allow a TX Scheduling Class to be
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
index 45b5853ca2f1..07a4619e2164 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
@@ -148,6 +148,32 @@ static int get_filter_steerq(struct net_device *dev,
 	return iq;
 }
 
+int cxgb4_get_free_ftid(struct net_device *dev, int family)
+{
+	struct adapter *adap = netdev2adap(dev);
+	struct tid_info *t = &adap->tids;
+	int ftid;
+
+	spin_lock_bh(&t->ftid_lock);
+	if (family == PF_INET) {
+		ftid = find_first_zero_bit(t->ftid_bmap, t->nftids);
+		if (ftid >= t->nftids)
+			ftid = -1;
+	} else {
+		ftid = bitmap_find_free_region(t->ftid_bmap, t->nftids, 2);
+		if (ftid < 0) {
+			ftid = -1;
+			goto out_unlock;
+		}
+
+		/* this is only a lookup, keep the found region unallocated */
+		bitmap_release_region(t->ftid_bmap, ftid, 2);
+	}
+out_unlock:
+	spin_unlock_bh(&t->ftid_lock);
+	return ftid;
+}
+
 static int cxgb4_set_ftid(struct tid_info *t, int fidx, int family)
 {
 	spin_lock_bh(&t->ftid_lock);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 8923affbdaf8..3ba4e1ff8486 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -5105,6 +5105,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		if (!adapter->tc_u32)
 			dev_warn(&pdev->dev,
 				 "could not offload tc u32, continuing\n");
+
+		cxgb4_init_tc_flower(adapter);
 	}
 
 	if (is_offload(adapter)) {
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
index 16dff71e4d02..1af01101faaf 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
@@ -38,16 +38,292 @@
 #include "cxgb4.h"
 #include "cxgb4_tc_flower.h"
 
+static struct ch_tc_flower_entry *allocate_flower_entry(void)
+{
+	struct ch_tc_flower_entry *new = kzalloc(sizeof(*new), GFP_KERNEL);
+	return new;
+}
+
+/* Must be called with either RTNL or rcu_read_lock */
+static struct ch_tc_flower_entry *ch_flower_lookup(struct adapter *adap,
+						   unsigned long flower_cookie)
+{
+	struct ch_tc_flower_entry *flower_entry;
+
+	hash_for_each_possible_rcu(adap->flower_anymatch_tbl, flower_entry,
+				   link, flower_cookie)
+		if (flower_entry->tc_flower_cookie == flower_cookie)
+			return flower_entry;
+	return NULL;
+}
+
+static void cxgb4_process_flow_match(struct net_device *dev,
+				     struct tc_cls_flower_offload *cls,
+				     struct ch_filter_specification *fs)
+{
+	u16 addr_type = 0;
+
+	if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
+		struct flow_dissector_key_control *key =
+			skb_flow_dissector_target(cls->dissector,
+						  FLOW_DISSECTOR_KEY_CONTROL,
+						  cls->key);
+
+		addr_type = key->addr_type;
+	}
+
+	if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
+		struct flow_dissector_key_basic *key =
+			skb_flow_dissector_target(cls->dissector,
+						  FLOW_DISSECTOR_KEY_BASIC,
+						  cls->key);
+		struct flow_dissector_key_basic *mask =
+			skb_flow_dissector_target(cls->dissector,
+						  FLOW_DISSECTOR_KEY_BASIC,
+						  cls->mask);
+		u16 ethtype_key = ntohs(key->n_proto);
+		u16 ethtype_mask = ntohs(mask->n_proto);
+
+		if (ethtype_key == ETH_P_ALL) {
+			ethtype_key = 0;
+			ethtype_mask = 0;
+		}
+
+		fs->val.ethtype = ethtype_key;
+		fs->mask.ethtype = ethtype_mask;
+		fs->val.proto = key->ip_proto;
+		fs->mask.proto = mask->ip_proto;
+	}
+
+	if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
+		struct flow_dissector_key_ipv4_addrs *key =
+			skb_flow_dissector_target(cls->dissector,
+						  FLOW_DISSECTOR_KEY_IPV4_ADDRS,
+						  cls->key);
+		struct flow_dissector_key_ipv4_addrs *mask =
+			skb_flow_dissector_target(cls->dissector,
+						  FLOW_DISSECTOR_KEY_IPV4_ADDRS,
+						  cls->mask);
+		fs->type = 0;
+		memcpy(&fs->val.lip[0], &key->dst, sizeof(key->dst));
+		memcpy(&fs->val.fip[0], &key->src, sizeof(key->src));
+		memcpy(&fs->mask.lip[0], &mask->dst, sizeof(mask->dst));
+		memcpy(&fs->mask.fip[0], &mask->src, sizeof(mask->src));
+	}
+
+	if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
+		struct flow_dissector_key_ipv6_addrs *key =
+			skb_flow_dissector_target(cls->dissector,
+						  FLOW_DISSECTOR_KEY_IPV6_ADDRS,
+						  cls->key);
+		struct flow_dissector_key_ipv6_addrs *mask =
+			skb_flow_dissector_target(cls->dissector,
+						  FLOW_DISSECTOR_KEY_IPV6_ADDRS,
+						  cls->mask);
+
+		fs->type = 1;
+		memcpy(&fs->val.lip[0], key->dst.s6_addr, sizeof(key->dst));
+		memcpy(&fs->val.fip[0], key->src.s6_addr, sizeof(key->src));
+		memcpy(&fs->mask.lip[0], mask->dst.s6_addr, sizeof(mask->dst));
+		memcpy(&fs->mask.fip[0], mask->src.s6_addr, sizeof(mask->src));
+	}
+
+	if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
+		struct flow_dissector_key_ports *key, *mask;
+
+		key = skb_flow_dissector_target(cls->dissector,
+						FLOW_DISSECTOR_KEY_PORTS,
+						cls->key);
+		mask = skb_flow_dissector_target(cls->dissector,
+						 FLOW_DISSECTOR_KEY_PORTS,
+						 cls->mask);
+		fs->val.lport = cpu_to_be16(key->dst);
+		fs->mask.lport = cpu_to_be16(mask->dst);
+		fs->val.fport = cpu_to_be16(key->src);
+		fs->mask.fport = cpu_to_be16(mask->src);
+	}
+
+	/* Match only packets coming from the ingress port where this
+	 * filter will be created.
+	 */
+	fs->val.iport = netdev2pinfo(dev)->port_id;
+	fs->mask.iport = ~0;
+}
+
+static int cxgb4_validate_flow_match(struct net_device *dev,
+				     struct tc_cls_flower_offload *cls)
+{
+	if (cls->dissector->used_keys &
+	    ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
+	      BIT(FLOW_DISSECTOR_KEY_BASIC) |
+	      BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
+	      BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
+	      BIT(FLOW_DISSECTOR_KEY_PORTS))) {
+		netdev_warn(dev, "Unsupported key used: 0x%x\n",
+			    cls->dissector->used_keys);
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
+static void cxgb4_process_flow_actions(struct net_device *in,
+				       struct tc_cls_flower_offload *cls,
+				       struct ch_filter_specification *fs)
+{
+	const struct tc_action *a;
+	LIST_HEAD(actions);
+
+	tcf_exts_to_list(cls->exts, &actions);
+	list_for_each_entry(a, &actions, list) {
+		if (is_tcf_gact_shot(a)) {
+			fs->action = FILTER_DROP;
+		} else if (is_tcf_mirred_egress_redirect(a)) {
+			int ifindex = tcf_mirred_ifindex(a);
+			struct net_device *out = __dev_get_by_index(dev_net(in),
+								    ifindex);
+			struct port_info *pi = netdev_priv(out);
+
+			fs->action = FILTER_SWITCH;
+			fs->eport = pi->port_id;
+		}
+	}
+}
+
+static int cxgb4_validate_flow_actions(struct net_device *dev,
+				       struct tc_cls_flower_offload *cls)
+{
+	const struct tc_action *a;
+	LIST_HEAD(actions);
+
+	tcf_exts_to_list(cls->exts, &actions);
+	list_for_each_entry(a, &actions, list) {
+		if (is_tcf_gact_shot(a)) {
+			/* Do nothing */
+		} else if (is_tcf_mirred_egress_redirect(a)) {
+			struct adapter *adap = netdev2adap(dev);
+			struct net_device *n_dev;
+			unsigned int i, ifindex;
+			bool found = false;
+
+			ifindex = tcf_mirred_ifindex(a);
+			for_each_port(adap, i) {
+				n_dev = adap->port[i];
+				if (ifindex == n_dev->ifindex) {
+					found = true;
+					break;
+				}
+			}
+
+			/* If interface doesn't belong to our hw, then
+			 * the provided output port is not valid
+			 */
+			if (!found) {
+				netdev_err(dev, "%s: Out port invalid\n",
+					   __func__);
+				return -EINVAL;
+			}
+		} else {
+			netdev_err(dev, "%s: Unsupported action\n", __func__);
+			return -EOPNOTSUPP;
+		}
+	}
+	return 0;
+}
+
 int cxgb4_tc_flower_replace(struct net_device *dev,
 			    struct tc_cls_flower_offload *cls)
 {
-	return -EOPNOTSUPP;
+	struct adapter *adap = netdev2adap(dev);
+	struct ch_tc_flower_entry *ch_flower;
+	struct ch_filter_specification *fs;
+	struct filter_ctx ctx;
+	int fidx;
+	int ret;
+
+	if (cxgb4_validate_flow_actions(dev, cls))
+		return -EOPNOTSUPP;
+
+	if (cxgb4_validate_flow_match(dev, cls))
+		return -EOPNOTSUPP;
+
+	ch_flower = allocate_flower_entry();
+	if (!ch_flower) {
+		netdev_err(dev, "%s: ch_flower alloc failed.\n", __func__);
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	fs = &ch_flower->fs;
+	fs->hitcnts = 1;
+	cxgb4_process_flow_actions(dev, cls, fs);
+	cxgb4_process_flow_match(dev, cls, fs);
+
+	fidx = cxgb4_get_free_ftid(dev, fs->type ? PF_INET6 : PF_INET);
+	if (fidx < 0) {
+		netdev_err(dev, "%s: No fidx for offload.\n", __func__);
+		ret = -ENOMEM;
+		goto free_entry;
+	}
+
+	init_completion(&ctx.completion);
+	ret = __cxgb4_set_filter(dev, fidx, fs, &ctx);
+	if (ret) {
+		netdev_err(dev, "%s: filter creation err %d\n",
+			   __func__, ret);
+		goto free_entry;
+	}
+
+	/* Wait for reply */
+	ret = wait_for_completion_timeout(&ctx.completion, 10 * HZ);
+	if (!ret) {
+		ret = -ETIMEDOUT;
+		goto free_entry;
+	}
+
+	ret = ctx.result;
+	/* Check if hw returned error for filter creation */
+	if (ret) {
+		netdev_err(dev, "%s: filter creation err %d\n",
+			   __func__, ret);
+		goto free_entry;
+	}
+
+	INIT_HLIST_NODE(&ch_flower->link);
+	ch_flower->tc_flower_cookie = cls->cookie;
+	ch_flower->filter_id = ctx.tid;
+	hash_add_rcu(adap->flower_anymatch_tbl, &ch_flower->link, cls->cookie);
+
+	return ret;
+
+free_entry:
+	kfree(ch_flower);
+err:
+	return ret;
 }
 
 int cxgb4_tc_flower_destroy(struct net_device *dev,
 			    struct tc_cls_flower_offload *cls)
 {
-	return -EOPNOTSUPP;
+	struct adapter *adap = netdev2adap(dev);
+	struct ch_tc_flower_entry *ch_flower;
+	int ret;
+
+	ch_flower = ch_flower_lookup(adap, cls->cookie);
+	if (!ch_flower) {
+		ret = -ENOENT;
+		goto err;
+	}
+
+	ret = cxgb4_del_filter(dev, ch_flower->filter_id);
+	if (ret)
+		goto err;
+
+	hash_del_rcu(&ch_flower->link);
+	kfree_rcu(ch_flower, rcu);
+	return ret;
+
+err:
+	return ret;
 }
 
 int cxgb4_tc_flower_stats(struct net_device *dev,
@@ -55,3 +331,8 @@ int cxgb4_tc_flower_stats(struct net_device *dev,
 {
 	return -EOPNOTSUPP;
 }
+
+void cxgb4_init_tc_flower(struct adapter *adap)
+{
+	hash_init(adap->flower_anymatch_tbl);
+}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
index b321fc205b5a..6145a9e056eb 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
@@ -37,10 +37,27 @@
 
 #include <net/pkt_cls.h>
 
+struct ch_tc_flower_stats {
+	u64 packet_count;
+	u64 byte_count;
+	u64 last_used;
+};
+
+struct ch_tc_flower_entry {
+	struct ch_filter_specification fs;
+	struct ch_tc_flower_stats stats;
+	unsigned long tc_flower_cookie;
+	struct hlist_node link;
+	struct rcu_head rcu;
+	u32 filter_id;
+};
+
 int cxgb4_tc_flower_replace(struct net_device *dev,
 			    struct tc_cls_flower_offload *cls);
 int cxgb4_tc_flower_destroy(struct net_device *dev,
 			    struct tc_cls_flower_offload *cls);
 int cxgb4_tc_flower_stats(struct net_device *dev,
 			  struct tc_cls_flower_offload *cls);
+
+void cxgb4_init_tc_flower(struct adapter *adap);
 #endif /* __CXGB4_TC_FLOWER_H */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index 84541fce94c5..88487095d14f 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -212,6 +212,7 @@ struct filter_ctx {
 
 struct ch_filter_specification;
 
+int cxgb4_get_free_ftid(struct net_device *dev, int family);
 int __cxgb4_set_filter(struct net_device *dev, int filter_id,
 		       struct ch_filter_specification *fs,
 		       struct filter_ctx *ctx);
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH net-next 3/4] cxgb4: add support to offload action vlan
  2017-09-21  7:33 [PATCH net-next 0/4] cxgb4: add support to offload tc flower Rahul Lakkireddy
  2017-09-21  7:33 ` [PATCH net-next 1/4] cxgb4: add tc flower offload skeleton Rahul Lakkireddy
  2017-09-21  7:33 ` [PATCH net-next 2/4] cxgb4: add basic tc flower offload support Rahul Lakkireddy
@ 2017-09-21  7:33 ` Rahul Lakkireddy
  2017-09-21  8:55   ` Jiri Pirko
  2017-09-21  7:33 ` [PATCH net-next 4/4] cxgb4: fetch stats for offloaded tc flower flows Rahul Lakkireddy
  2017-09-21  8:56 ` [PATCH net-next 0/4] cxgb4: add support to offload tc flower Jiri Pirko
  4 siblings, 1 reply; 10+ messages in thread
From: Rahul Lakkireddy @ 2017-09-21  7:33 UTC (permalink / raw)
  To: netdev; +Cc: davem, kumaras, ganeshgr, nirranjan, indranil, Rahul Lakkireddy

From: Kumar Sanghvi <kumaras@chelsio.com>

Add support for offloading tc-flower flows having
vlan actions: pop, push and modify.

Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
---
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c   | 43 ++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
index 1af01101faaf..fddb0c419edc 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
@@ -34,6 +34,7 @@
 
 #include <net/tc_act/tc_gact.h>
 #include <net/tc_act/tc_mirred.h>
+#include <net/tc_act/tc_vlan.h>
 
 #include "cxgb4.h"
 #include "cxgb4_tc_flower.h"
@@ -185,6 +186,27 @@ static void cxgb4_process_flow_actions(struct net_device *in,
 
 			fs->action = FILTER_SWITCH;
 			fs->eport = pi->port_id;
+		} else if (is_tcf_vlan(a)) {
+			u32 vlan_action = tcf_vlan_action(a);
+			u8 prio = tcf_vlan_push_prio(a);
+			u16 vid = tcf_vlan_push_vid(a);
+			u16 vlan_tci = (prio << VLAN_PRIO_SHIFT) | vid;
+
+			switch (vlan_action) {
+			case TCA_VLAN_ACT_POP:
+				fs->newvlan |= VLAN_REMOVE;
+				break;
+			case TCA_VLAN_ACT_PUSH:
+				fs->newvlan |= VLAN_INSERT;
+				fs->vlan = vlan_tci;
+				break;
+			case TCA_VLAN_ACT_MODIFY:
+				fs->newvlan |= VLAN_REWRITE;
+				fs->vlan = vlan_tci;
+				break;
+			default:
+				break;
+			}
 		}
 	}
 }
@@ -222,6 +244,27 @@ static int cxgb4_validate_flow_actions(struct net_device *dev,
 					   __func__);
 				return -EINVAL;
 			}
+		} else if (is_tcf_vlan(a)) {
+			u16 proto = be16_to_cpu(tcf_vlan_push_proto(a));
+			u32 vlan_action = tcf_vlan_action(a);
+
+			switch (vlan_action) {
+			case TCA_VLAN_ACT_POP:
+				break;
+			case TCA_VLAN_ACT_PUSH:
+			case TCA_VLAN_ACT_MODIFY:
+				if (proto != ETH_P_8021Q) {
+					netdev_err(dev,
+						   "%s: Unsupp. vlan proto\n",
+						   __func__);
+					return -EOPNOTSUPP;
+				}
+				break;
+			default:
+				netdev_err(dev, "%s: Unsupported vlan action\n",
+					   __func__);
+				return -EOPNOTSUPP;
+			}
 		} else {
 			netdev_err(dev, "%s: Unsupported action\n", __func__);
 			return -EOPNOTSUPP;
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH net-next 4/4] cxgb4: fetch stats for offloaded tc flower flows
  2017-09-21  7:33 [PATCH net-next 0/4] cxgb4: add support to offload tc flower Rahul Lakkireddy
                   ` (2 preceding siblings ...)
  2017-09-21  7:33 ` [PATCH net-next 3/4] cxgb4: add support to offload action vlan Rahul Lakkireddy
@ 2017-09-21  7:33 ` Rahul Lakkireddy
  2017-09-21  8:56 ` [PATCH net-next 0/4] cxgb4: add support to offload tc flower Jiri Pirko
  4 siblings, 0 replies; 10+ messages in thread
From: Rahul Lakkireddy @ 2017-09-21  7:33 UTC (permalink / raw)
  To: netdev; +Cc: davem, kumaras, ganeshgr, nirranjan, indranil, Rahul Lakkireddy

From: Kumar Sanghvi <kumaras@chelsio.com>

Add support to retrieve stats from hardware for offloaded tc flower
flows.  Also, poll for the stats of offloaded flows via timer callback.

Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
---
 drivers/net/ethernet/chelsio/cxgb4/cxgb4.h         |  1 +
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c  | 76 +++++++++++++++++++++
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c    |  1 +
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c   | 79 +++++++++++++++++++++-
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h   |  3 +
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h     |  2 +
 6 files changed, 161 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 26eac599ab2c..8a94d97df025 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -907,6 +907,7 @@ struct adapter {
 
 	/* TC flower offload */
 	DECLARE_HASHTABLE(flower_anymatch_tbl, 9);
+	struct timer_list flower_stats_timer;
 };
 
 /* Support for "sched-class" command to allow a TX Scheduling Class to be
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
index 07a4619e2164..c09c4de8c9fb 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
@@ -148,6 +148,82 @@ static int get_filter_steerq(struct net_device *dev,
 	return iq;
 }
 
+static int get_filter_count(struct adapter *adapter, unsigned int fidx,
+			    u64 *pkts, u64 *bytes)
+{
+	unsigned int tcb_base, tcbaddr;
+	unsigned int word_offset;
+	struct filter_entry *f;
+	__be64 be64_byte_count;
+	int ret;
+
+	tcb_base = t4_read_reg(adapter, TP_CMM_TCB_BASE_A);
+	if ((fidx != (adapter->tids.nftids + adapter->tids.nsftids - 1)) &&
+	    fidx >= adapter->tids.nftids)
+		return -E2BIG;
+
+	f = &adapter->tids.ftid_tab[fidx];
+	if (!f->valid)
+		return -EINVAL;
+
+	tcbaddr = tcb_base + f->tid * TCB_SIZE;
+
+	spin_lock(&adapter->win0_lock);
+	if (is_t4(adapter->params.chip)) {
+		__be64 be64_count;
+
+		/* T4 doesn't maintain byte counts in hw */
+		*bytes = 0;
+
+		/* Get pkts */
+		word_offset = 4;
+		ret = t4_memory_rw(adapter, MEMWIN_NIC, MEM_EDC0,
+				   tcbaddr + (word_offset * sizeof(__be32)),
+				   sizeof(be64_count),
+				   (__be32 *)&be64_count,
+				   T4_MEMORY_READ);
+		if (ret < 0)
+			goto out;
+		*pkts = be64_to_cpu(be64_count);
+	} else {
+		__be32 be32_count;
+
+		/* Get bytes */
+		word_offset = 4;
+		ret = t4_memory_rw(adapter, MEMWIN_NIC, MEM_EDC0,
+				   tcbaddr + (word_offset * sizeof(__be32)),
+				   sizeof(be64_byte_count),
+				   &be64_byte_count,
+				   T4_MEMORY_READ);
+		if (ret < 0)
+			goto out;
+		*bytes = be64_to_cpu(be64_byte_count);
+
+		/* Get pkts */
+		word_offset = 6;
+		ret = t4_memory_rw(adapter, MEMWIN_NIC, MEM_EDC0,
+				   tcbaddr + (word_offset * sizeof(__be32)),
+				   sizeof(be32_count),
+				   &be32_count,
+				   T4_MEMORY_READ);
+		if (ret < 0)
+			goto out;
+		*pkts = (u64)be32_to_cpu(be32_count);
+	}
+
+out:
+	spin_unlock(&adapter->win0_lock);
+	return ret;
+}
+
+int cxgb4_get_filter_counters(struct net_device *dev, unsigned int fidx,
+			      u64 *hitcnt, u64 *bytecnt)
+{
+	struct adapter *adapter = netdev2adap(dev);
+
+	return get_filter_count(adapter, fidx, hitcnt, bytecnt);
+}
+
 int cxgb4_get_free_ftid(struct net_device *dev, int family)
 {
 	struct adapter *adap = netdev2adap(dev);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 3ba4e1ff8486..d634098d52ab 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -4637,6 +4637,7 @@ static void free_some_resources(struct adapter *adapter)
 	kvfree(adapter->l2t);
 	t4_cleanup_sched(adapter);
 	kvfree(adapter->tids.tid_tab);
+	cxgb4_cleanup_tc_flower(adapter);
 	cxgb4_cleanup_tc_u32(adapter);
 	kfree(adapter->sge.egr_map);
 	kfree(adapter->sge.ingr_map);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
index fddb0c419edc..7a47d4e88a57 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
@@ -39,9 +39,12 @@
 #include "cxgb4.h"
 #include "cxgb4_tc_flower.h"
 
+#define STATS_CHECK_PERIOD (HZ / 2)
+
 static struct ch_tc_flower_entry *allocate_flower_entry(void)
 {
 	struct ch_tc_flower_entry *new = kzalloc(sizeof(*new), GFP_KERNEL);
+	spin_lock_init(&new->lock);
 	return new;
 }
 
@@ -369,13 +372,87 @@ int cxgb4_tc_flower_destroy(struct net_device *dev,
 	return ret;
 }
 
+void ch_flower_stats_cb(unsigned long data)
+{
+	struct adapter *adap = (struct adapter *)data;
+	struct ch_tc_flower_entry *flower_entry;
+	struct ch_tc_flower_stats *ofld_stats;
+	unsigned int i;
+	u64 packets;
+	u64 bytes;
+	int ret;
+
+	rcu_read_lock();
+	hash_for_each_rcu(adap->flower_anymatch_tbl, i, flower_entry, link) {
+		ret = cxgb4_get_filter_counters(adap->port[0],
+						flower_entry->filter_id,
+						&packets, &bytes);
+		if (!ret) {
+			spin_lock(&flower_entry->lock);
+			ofld_stats = &flower_entry->stats;
+
+			if (ofld_stats->prev_packet_count != packets) {
+				ofld_stats->prev_packet_count = packets;
+				ofld_stats->last_used = jiffies;
+			}
+			spin_unlock(&flower_entry->lock);
+		}
+	}
+	rcu_read_unlock();
+	mod_timer(&adap->flower_stats_timer, jiffies + STATS_CHECK_PERIOD);
+}
+
 int cxgb4_tc_flower_stats(struct net_device *dev,
 			  struct tc_cls_flower_offload *cls)
 {
-	return -EOPNOTSUPP;
+	struct adapter *adap = netdev2adap(dev);
+	struct ch_tc_flower_stats *ofld_stats;
+	struct ch_tc_flower_entry *ch_flower;
+	u64 packets;
+	u64 bytes;
+	int ret;
+
+	ch_flower = ch_flower_lookup(adap, cls->cookie);
+	if (!ch_flower) {
+		ret = -ENOENT;
+		goto err;
+	}
+
+	ret = cxgb4_get_filter_counters(dev, ch_flower->filter_id,
+					&packets, &bytes);
+	if (ret < 0)
+		goto err;
+
+	spin_lock_bh(&ch_flower->lock);
+	ofld_stats = &ch_flower->stats;
+	if (ofld_stats->packet_count != packets) {
+		if (ofld_stats->prev_packet_count != packets)
+			ofld_stats->last_used = jiffies;
+		tcf_exts_stats_update(cls->exts, bytes - ofld_stats->byte_count,
+				      packets - ofld_stats->packet_count,
+				      ofld_stats->last_used);
+
+		ofld_stats->packet_count = packets;
+		ofld_stats->byte_count = bytes;
+		ofld_stats->prev_packet_count = packets;
+	}
+	spin_unlock_bh(&ch_flower->lock);
+	return 0;
+
+err:
+	return ret;
 }
 
 void cxgb4_init_tc_flower(struct adapter *adap)
 {
 	hash_init(adap->flower_anymatch_tbl);
+	setup_timer(&adap->flower_stats_timer, ch_flower_stats_cb,
+		    (unsigned long)adap);
+	mod_timer(&adap->flower_stats_timer, jiffies + STATS_CHECK_PERIOD);
+}
+
+void cxgb4_cleanup_tc_flower(struct adapter *adap)
+{
+	if (adap->flower_stats_timer.function)
+		del_timer_sync(&adap->flower_stats_timer);
 }
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
index 6145a9e056eb..604feffc752e 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
@@ -38,6 +38,7 @@
 #include <net/pkt_cls.h>
 
 struct ch_tc_flower_stats {
+	u64 prev_packet_count;
 	u64 packet_count;
 	u64 byte_count;
 	u64 last_used;
@@ -49,6 +50,7 @@ struct ch_tc_flower_entry {
 	unsigned long tc_flower_cookie;
 	struct hlist_node link;
 	struct rcu_head rcu;
+	spinlock_t lock; /* lock for stats */
 	u32 filter_id;
 };
 
@@ -60,4 +62,5 @@ int cxgb4_tc_flower_stats(struct net_device *dev,
 			  struct tc_cls_flower_offload *cls);
 
 void cxgb4_init_tc_flower(struct adapter *adap);
+void cxgb4_cleanup_tc_flower(struct adapter *adap);
 #endif /* __CXGB4_TC_FLOWER_H */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index 88487095d14f..52324c77a4fe 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -221,6 +221,8 @@ int __cxgb4_del_filter(struct net_device *dev, int filter_id,
 int cxgb4_set_filter(struct net_device *dev, int filter_id,
 		     struct ch_filter_specification *fs);
 int cxgb4_del_filter(struct net_device *dev, int filter_id);
+int cxgb4_get_filter_counters(struct net_device *dev, unsigned int fidx,
+			      u64 *hitcnt, u64 *bytecnt);
 
 static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue)
 {
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH net-next 3/4] cxgb4: add support to offload action vlan
  2017-09-21  7:33 ` [PATCH net-next 3/4] cxgb4: add support to offload action vlan Rahul Lakkireddy
@ 2017-09-21  8:55   ` Jiri Pirko
  2017-09-21 15:23     ` Kumar Sanghvi
  0 siblings, 1 reply; 10+ messages in thread
From: Jiri Pirko @ 2017-09-21  8:55 UTC (permalink / raw)
  To: Rahul Lakkireddy; +Cc: netdev, davem, kumaras, ganeshgr, nirranjan, indranil

Thu, Sep 21, 2017 at 09:33:36AM CEST, rahul.lakkireddy@chelsio.com wrote:
>From: Kumar Sanghvi <kumaras@chelsio.com>
>
>Add support for offloading tc-flower flows having
>vlan actions: pop, push and modify.
>
>Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
>Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
>Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
>---
> .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c   | 43 ++++++++++++++++++++++
> 1 file changed, 43 insertions(+)
>
>diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c

[...]


>+			switch (vlan_action) {
>+			case TCA_VLAN_ACT_POP:
>+				break;
>+			case TCA_VLAN_ACT_PUSH:
>+			case TCA_VLAN_ACT_MODIFY:
>+				if (proto != ETH_P_8021Q) {
>+					netdev_err(dev,
>+						   "%s: Unsupp. vlan proto\n",

Don't wrap this. Also "Unsupp."vs"Unsupported". Please be consistent.


>+						   __func__);
>+					return -EOPNOTSUPP;
>+				}
>+				break;
>+			default:
>+				netdev_err(dev, "%s: Unsupported vlan action\n",
>+					   __func__);
>+				return -EOPNOTSUPP;
>+			}
> 		} else {
> 			netdev_err(dev, "%s: Unsupported action\n", __func__);
> 			return -EOPNOTSUPP;
>-- 
>2.14.1
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH net-next 0/4] cxgb4: add support to offload tc flower
  2017-09-21  7:33 [PATCH net-next 0/4] cxgb4: add support to offload tc flower Rahul Lakkireddy
                   ` (3 preceding siblings ...)
  2017-09-21  7:33 ` [PATCH net-next 4/4] cxgb4: fetch stats for offloaded tc flower flows Rahul Lakkireddy
@ 2017-09-21  8:56 ` Jiri Pirko
  4 siblings, 0 replies; 10+ messages in thread
From: Jiri Pirko @ 2017-09-21  8:56 UTC (permalink / raw)
  To: Rahul Lakkireddy; +Cc: netdev, davem, kumaras, ganeshgr, nirranjan, indranil

Thu, Sep 21, 2017 at 09:33:33AM CEST, rahul.lakkireddy@chelsio.com wrote:
>This series of patches add support to offload tc flower onto Chelsio
>NICs.
>
>Patch 1 adds basic skeleton to prepare for offloading tc flower flows.
>
>Patch 2 adds support to add/remove flows for offload.  Flows can have
>accompanying masks.  Following match and action are currently supported
>for offload:
>Match:  ether-protocol, IPv4/IPv6 addresses, L4 ports (TCP/UDP)
>Action: drop, redirect to another port on the device.
>
>Patch 3 adds support to offload tc-flower flows having
>vlan actions: pop, push, and modify.
>
>Patch 4 adds support to fetch stats for the offloaded tc flower flows
>from hardware.
>
>Support for offloading more match and action types are to be followed
>in subsequent series.

Looks good to me. Thanks!

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH net-next 2/4] cxgb4: add basic tc flower offload support
  2017-09-21  7:33 ` [PATCH net-next 2/4] cxgb4: add basic tc flower offload support Rahul Lakkireddy
@ 2017-09-21 10:55   ` Yunsheng Lin
  2017-09-21 15:31     ` Kumar Sanghvi
  0 siblings, 1 reply; 10+ messages in thread
From: Yunsheng Lin @ 2017-09-21 10:55 UTC (permalink / raw)
  To: Rahul Lakkireddy, netdev; +Cc: davem, kumaras, ganeshgr, nirranjan, indranil

Hi, Kumar

On 2017/9/21 15:33, Rahul Lakkireddy wrote:
> From: Kumar Sanghvi <kumaras@chelsio.com>
> 
> Add support to add/remove flows for offload.  Following match
> and action are supported for offloading a flow:
> 
> Match: ether-protocol, IPv4/IPv6 addresses, L4 ports (TCP/UDP)
> Action: drop, redirect to another port on the device.
> 
> The qualifying flows can have accompanying mask information.
> 
> Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
> Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
> Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
> ---
>  drivers/net/ethernet/chelsio/cxgb4/cxgb4.h         |   3 +
>  drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c  |  26 ++
>  drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c    |   2 +
>  .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c   | 285 ++++++++++++++++++++-
>  .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h   |  17 ++
>  drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h     |   1 +
>  6 files changed, 332 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
> index ea72d2d2e1b4..26eac599ab2c 100644
> --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
> +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
> @@ -904,6 +904,9 @@ struct adapter {
>  	/* TC u32 offload */
>  	struct cxgb4_tc_u32_table *tc_u32;
>  	struct chcr_stats_debug chcr_stats;
> +
> +	/* TC flower offload */
> +	DECLARE_HASHTABLE(flower_anymatch_tbl, 9);
>  };
>  
>  /* Support for "sched-class" command to allow a TX Scheduling Class to be
> diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
> index 45b5853ca2f1..07a4619e2164 100644
> --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
> +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
> @@ -148,6 +148,32 @@ static int get_filter_steerq(struct net_device *dev,
>  	return iq;
>  }
>  
> +int cxgb4_get_free_ftid(struct net_device *dev, int family)
> +{
> +	struct adapter *adap = netdev2adap(dev);
> +	struct tid_info *t = &adap->tids;
> +	int ftid;
> +
> +	spin_lock_bh(&t->ftid_lock);
> +	if (family == PF_INET) {
> +		ftid = find_first_zero_bit(t->ftid_bmap, t->nftids);
> +		if (ftid >= t->nftids)
> +			ftid = -1;
> +	} else {
> +		ftid = bitmap_find_free_region(t->ftid_bmap, t->nftids, 2);
> +		if (ftid < 0) {
> +			ftid = -1;

ftid = -1 is not needed?

> +			goto out_unlock;
> +		}
> +
> +		/* this is only a lookup, keep the found region unallocated */
> +		bitmap_release_region(t->ftid_bmap, ftid, 2);
> +	}
> +out_unlock:
> +	spin_unlock_bh(&t->ftid_lock);
> +	return ftid;
> +}
> +
>  static int cxgb4_set_ftid(struct tid_info *t, int fidx, int family)
>  {
>  	spin_lock_bh(&t->ftid_lock);
> diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
> index 8923affbdaf8..3ba4e1ff8486 100644
> --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
> +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
> @@ -5105,6 +5105,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>  		if (!adapter->tc_u32)
>  			dev_warn(&pdev->dev,
>  				 "could not offload tc u32, continuing\n");
> +
> +		cxgb4_init_tc_flower(adapter);
>  	}
>  
>  	if (is_offload(adapter)) {
> diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
> index 16dff71e4d02..1af01101faaf 100644
> --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
> +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
> @@ -38,16 +38,292 @@
>  #include "cxgb4.h"
>  #include "cxgb4_tc_flower.h"
>  
> +static struct ch_tc_flower_entry *allocate_flower_entry(void)
> +{
> +	struct ch_tc_flower_entry *new = kzalloc(sizeof(*new), GFP_KERNEL);
> +	return new;
> +}
> +
> +/* Must be called with either RTNL or rcu_read_lock */
> +static struct ch_tc_flower_entry *ch_flower_lookup(struct adapter *adap,
> +						   unsigned long flower_cookie)
> +{
> +	struct ch_tc_flower_entry *flower_entry;
> +
> +	hash_for_each_possible_rcu(adap->flower_anymatch_tbl, flower_entry,
> +				   link, flower_cookie)
> +		if (flower_entry->tc_flower_cookie == flower_cookie)
> +			return flower_entry;
> +	return NULL;
> +}
> +
> +static void cxgb4_process_flow_match(struct net_device *dev,
> +				     struct tc_cls_flower_offload *cls,
> +				     struct ch_filter_specification *fs)
> +{
> +	u16 addr_type = 0;
> +
> +	if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
> +		struct flow_dissector_key_control *key =
> +			skb_flow_dissector_target(cls->dissector,
> +						  FLOW_DISSECTOR_KEY_CONTROL,
> +						  cls->key);
> +
> +		addr_type = key->addr_type;
> +	}
> +
> +	if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
> +		struct flow_dissector_key_basic *key =
> +			skb_flow_dissector_target(cls->dissector,
> +						  FLOW_DISSECTOR_KEY_BASIC,
> +						  cls->key);
> +		struct flow_dissector_key_basic *mask =
> +			skb_flow_dissector_target(cls->dissector,
> +						  FLOW_DISSECTOR_KEY_BASIC,
> +						  cls->mask);
> +		u16 ethtype_key = ntohs(key->n_proto);
> +		u16 ethtype_mask = ntohs(mask->n_proto);
> +
> +		if (ethtype_key == ETH_P_ALL) {
> +			ethtype_key = 0;
> +			ethtype_mask = 0;
> +		}
> +
> +		fs->val.ethtype = ethtype_key;
> +		fs->mask.ethtype = ethtype_mask;
> +		fs->val.proto = key->ip_proto;
> +		fs->mask.proto = mask->ip_proto;
> +	}
> +
> +	if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
> +		struct flow_dissector_key_ipv4_addrs *key =
> +			skb_flow_dissector_target(cls->dissector,
> +						  FLOW_DISSECTOR_KEY_IPV4_ADDRS,
> +						  cls->key);
> +		struct flow_dissector_key_ipv4_addrs *mask =
> +			skb_flow_dissector_target(cls->dissector,
> +						  FLOW_DISSECTOR_KEY_IPV4_ADDRS,
> +						  cls->mask);
> +		fs->type = 0;
> +		memcpy(&fs->val.lip[0], &key->dst, sizeof(key->dst));
> +		memcpy(&fs->val.fip[0], &key->src, sizeof(key->src));
> +		memcpy(&fs->mask.lip[0], &mask->dst, sizeof(mask->dst));
> +		memcpy(&fs->mask.fip[0], &mask->src, sizeof(mask->src));
> +	}
> +
> +	if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
> +		struct flow_dissector_key_ipv6_addrs *key =
> +			skb_flow_dissector_target(cls->dissector,
> +						  FLOW_DISSECTOR_KEY_IPV6_ADDRS,
> +						  cls->key);
> +		struct flow_dissector_key_ipv6_addrs *mask =
> +			skb_flow_dissector_target(cls->dissector,
> +						  FLOW_DISSECTOR_KEY_IPV6_ADDRS,
> +						  cls->mask);
> +
> +		fs->type = 1;
> +		memcpy(&fs->val.lip[0], key->dst.s6_addr, sizeof(key->dst));
> +		memcpy(&fs->val.fip[0], key->src.s6_addr, sizeof(key->src));
> +		memcpy(&fs->mask.lip[0], mask->dst.s6_addr, sizeof(mask->dst));
> +		memcpy(&fs->mask.fip[0], mask->src.s6_addr, sizeof(mask->src));
> +	}
> +
> +	if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
> +		struct flow_dissector_key_ports *key, *mask;
> +
> +		key = skb_flow_dissector_target(cls->dissector,
> +						FLOW_DISSECTOR_KEY_PORTS,
> +						cls->key);
> +		mask = skb_flow_dissector_target(cls->dissector,
> +						 FLOW_DISSECTOR_KEY_PORTS,
> +						 cls->mask);
> +		fs->val.lport = cpu_to_be16(key->dst);
> +		fs->mask.lport = cpu_to_be16(mask->dst);
> +		fs->val.fport = cpu_to_be16(key->src);
> +		fs->mask.fport = cpu_to_be16(mask->src);
> +	}
> +
> +	/* Match only packets coming from the ingress port where this
> +	 * filter will be created.
> +	 */
> +	fs->val.iport = netdev2pinfo(dev)->port_id;
> +	fs->mask.iport = ~0;
> +}
> +
> +static int cxgb4_validate_flow_match(struct net_device *dev,
> +				     struct tc_cls_flower_offload *cls)
> +{
> +	if (cls->dissector->used_keys &
> +	    ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
> +	      BIT(FLOW_DISSECTOR_KEY_BASIC) |
> +	      BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
> +	      BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
> +	      BIT(FLOW_DISSECTOR_KEY_PORTS))) {
> +		netdev_warn(dev, "Unsupported key used: 0x%x\n",
> +			    cls->dissector->used_keys);
> +		return -EOPNOTSUPP;
> +	}
> +	return 0;
> +}
> +
> +static void cxgb4_process_flow_actions(struct net_device *in,
> +				       struct tc_cls_flower_offload *cls,
> +				       struct ch_filter_specification *fs)
> +{
> +	const struct tc_action *a;
> +	LIST_HEAD(actions);
> +
> +	tcf_exts_to_list(cls->exts, &actions);
> +	list_for_each_entry(a, &actions, list) {
> +		if (is_tcf_gact_shot(a)) {
> +			fs->action = FILTER_DROP;
> +		} else if (is_tcf_mirred_egress_redirect(a)) {
> +			int ifindex = tcf_mirred_ifindex(a);
> +			struct net_device *out = __dev_get_by_index(dev_net(in),
> +								    ifindex);
> +			struct port_info *pi = netdev_priv(out);
> +
> +			fs->action = FILTER_SWITCH;
> +			fs->eport = pi->port_id;
> +		}
> +	}
> +}
> +
> +static int cxgb4_validate_flow_actions(struct net_device *dev,
> +				       struct tc_cls_flower_offload *cls)
> +{
> +	const struct tc_action *a;
> +	LIST_HEAD(actions);
> +
> +	tcf_exts_to_list(cls->exts, &actions);
> +	list_for_each_entry(a, &actions, list) {
> +		if (is_tcf_gact_shot(a)) {
> +			/* Do nothing */
> +		} else if (is_tcf_mirred_egress_redirect(a)) {
> +			struct adapter *adap = netdev2adap(dev);
> +			struct net_device *n_dev;
> +			unsigned int i, ifindex;
> +			bool found = false;
> +
> +			ifindex = tcf_mirred_ifindex(a);
> +			for_each_port(adap, i) {
> +				n_dev = adap->port[i];
> +				if (ifindex == n_dev->ifindex) {
> +					found = true;
> +					break;
> +				}
> +			}
> +
> +			/* If interface doesn't belong to our hw, then
> +			 * the provided output port is not valid
> +			 */
> +			if (!found) {
> +				netdev_err(dev, "%s: Out port invalid\n",
> +					   __func__);
> +				return -EINVAL;
> +			}
> +		} else {
> +			netdev_err(dev, "%s: Unsupported action\n", __func__);
> +			return -EOPNOTSUPP;
> +		}
> +	}
> +	return 0;
> +}
> +
>  int cxgb4_tc_flower_replace(struct net_device *dev,
>  			    struct tc_cls_flower_offload *cls)
>  {
> -	return -EOPNOTSUPP;
> +	struct adapter *adap = netdev2adap(dev);
> +	struct ch_tc_flower_entry *ch_flower;
> +	struct ch_filter_specification *fs;
> +	struct filter_ctx ctx;
> +	int fidx;
> +	int ret;
> +
> +	if (cxgb4_validate_flow_actions(dev, cls))
> +		return -EOPNOTSUPP;
> +
> +	if (cxgb4_validate_flow_match(dev, cls))
> +		return -EOPNOTSUPP;
> +
> +	ch_flower = allocate_flower_entry();
> +	if (!ch_flower) {
> +		netdev_err(dev, "%s: ch_flower alloc failed.\n", __func__);
> +		ret = -ENOMEM;
> +		goto err;

Just return, err label is needed?

> +	}
> +
> +	fs = &ch_flower->fs;
> +	fs->hitcnts = 1;
> +	cxgb4_process_flow_actions(dev, cls, fs);
> +	cxgb4_process_flow_match(dev, cls, fs);
> +
> +	fidx = cxgb4_get_free_ftid(dev, fs->type ? PF_INET6 : PF_INET);
> +	if (fidx < 0) {
> +		netdev_err(dev, "%s: No fidx for offload.\n", __func__);
> +		ret = -ENOMEM;
> +		goto free_entry;
> +	}
> +
> +	init_completion(&ctx.completion);
> +	ret = __cxgb4_set_filter(dev, fidx, fs, &ctx);
> +	if (ret) {
> +		netdev_err(dev, "%s: filter creation err %d\n",
> +			   __func__, ret);
> +		goto free_entry;
> +	}
> +
> +	/* Wait for reply */
> +	ret = wait_for_completion_timeout(&ctx.completion, 10 * HZ);
> +	if (!ret) {
> +		ret = -ETIMEDOUT;
> +		goto free_entry;
> +	}
> +
> +	ret = ctx.result;
> +	/* Check if hw returned error for filter creation */
> +	if (ret) {
> +		netdev_err(dev, "%s: filter creation err %d\n",
> +			   __func__, ret);
> +		goto free_entry;
> +	}
> +
> +	INIT_HLIST_NODE(&ch_flower->link);
> +	ch_flower->tc_flower_cookie = cls->cookie;
> +	ch_flower->filter_id = ctx.tid;
> +	hash_add_rcu(adap->flower_anymatch_tbl, &ch_flower->link, cls->cookie);
> +
> +	return ret;
> +
> +free_entry:
> +	kfree(ch_flower);
> +err:
> +	return ret;
>  }
>  
>  int cxgb4_tc_flower_destroy(struct net_device *dev,
>  			    struct tc_cls_flower_offload *cls)
>  {
> -	return -EOPNOTSUPP;
> +	struct adapter *adap = netdev2adap(dev);
> +	struct ch_tc_flower_entry *ch_flower;
> +	int ret;
> +
> +	ch_flower = ch_flower_lookup(adap, cls->cookie);
> +	if (!ch_flower) {
> +		ret = -ENOENT;
> +		goto err;

Same as above

> +	}
> +
> +	ret = cxgb4_del_filter(dev, ch_flower->filter_id);
> +	if (ret)
> +		goto err;
> +
> +	hash_del_rcu(&ch_flower->link);
> +	kfree_rcu(ch_flower, rcu);
> +	return ret;
> +
> +err:
> +	return ret;
>  }
>  
>  int cxgb4_tc_flower_stats(struct net_device *dev,
> @@ -55,3 +331,8 @@ int cxgb4_tc_flower_stats(struct net_device *dev,
>  {
>  	return -EOPNOTSUPP;
>  }
> +
> +void cxgb4_init_tc_flower(struct adapter *adap)
> +{
> +	hash_init(adap->flower_anymatch_tbl);
> +}
> diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
> index b321fc205b5a..6145a9e056eb 100644
> --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
> +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
> @@ -37,10 +37,27 @@
>  
>  #include <net/pkt_cls.h>
>  
> +struct ch_tc_flower_stats {
> +	u64 packet_count;
> +	u64 byte_count;
> +	u64 last_used;
> +};
> +
> +struct ch_tc_flower_entry {
> +	struct ch_filter_specification fs;
> +	struct ch_tc_flower_stats stats;
> +	unsigned long tc_flower_cookie;
> +	struct hlist_node link;
> +	struct rcu_head rcu;
> +	u32 filter_id;
> +};
> +
>  int cxgb4_tc_flower_replace(struct net_device *dev,
>  			    struct tc_cls_flower_offload *cls);
>  int cxgb4_tc_flower_destroy(struct net_device *dev,
>  			    struct tc_cls_flower_offload *cls);
>  int cxgb4_tc_flower_stats(struct net_device *dev,
>  			  struct tc_cls_flower_offload *cls);
> +
> +void cxgb4_init_tc_flower(struct adapter *adap);
>  #endif /* __CXGB4_TC_FLOWER_H */
> diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
> index 84541fce94c5..88487095d14f 100644
> --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
> +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
> @@ -212,6 +212,7 @@ struct filter_ctx {
>  
>  struct ch_filter_specification;
>  
> +int cxgb4_get_free_ftid(struct net_device *dev, int family);
>  int __cxgb4_set_filter(struct net_device *dev, int filter_id,
>  		       struct ch_filter_specification *fs,
>  		       struct filter_ctx *ctx);
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH net-next 3/4] cxgb4: add support to offload action vlan
  2017-09-21  8:55   ` Jiri Pirko
@ 2017-09-21 15:23     ` Kumar Sanghvi
  0 siblings, 0 replies; 10+ messages in thread
From: Kumar Sanghvi @ 2017-09-21 15:23 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: Rahul Lakkireddy, netdev, davem, ganeshgr, nirranjan, indranil

Hi Jiri,

On Thursday, September 09/21/17, 2017 at 10:55:08 +0200, Jiri Pirko wrote:
> Thu, Sep 21, 2017 at 09:33:36AM CEST, rahul.lakkireddy@chelsio.com wrote:
> >From: Kumar Sanghvi <kumaras@chelsio.com>
> >
> >Add support for offloading tc-flower flows having
> >vlan actions: pop, push and modify.
> >
> >Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
> >Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
> >Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
> >---
> > .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c   | 43 ++++++++++++++++++++++
> > 1 file changed, 43 insertions(+)
> >
> >diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
> 
> [...]
> 
> 
> >+			switch (vlan_action) {
> >+			case TCA_VLAN_ACT_POP:
> >+				break;
> >+			case TCA_VLAN_ACT_PUSH:
> >+			case TCA_VLAN_ACT_MODIFY:
> >+				if (proto != ETH_P_8021Q) {
> >+					netdev_err(dev,
> >+						   "%s: Unsupp. vlan proto\n",
> 
> Don't wrap this. Also "Unsupp."vs"Unsupported". Please be consistent.

Thank you for pointing this.
I will take care of this in V2.

> 
> 
> >+						   __func__);
> >+					return -EOPNOTSUPP;
> >+				}
> >+				break;
> >+			default:
> >+				netdev_err(dev, "%s: Unsupported vlan action\n",
> >+					   __func__);
> >+				return -EOPNOTSUPP;
> >+			}
> > 		} else {
> > 			netdev_err(dev, "%s: Unsupported action\n", __func__);
> > 			return -EOPNOTSUPP;
> >-- 
> >2.14.1
> >

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH net-next 2/4] cxgb4: add basic tc flower offload support
  2017-09-21 10:55   ` Yunsheng Lin
@ 2017-09-21 15:31     ` Kumar Sanghvi
  0 siblings, 0 replies; 10+ messages in thread
From: Kumar Sanghvi @ 2017-09-21 15:31 UTC (permalink / raw)
  To: Yunsheng Lin
  Cc: Rahul Lakkireddy, netdev, davem, ganeshgr, nirranjan, indranil

Hi Yunsheng,

On Thursday, September 09/21/17, 2017 at 18:55:26 +0800, Yunsheng Lin wrote:
> Hi, Kumar
> 
> On 2017/9/21 15:33, Rahul Lakkireddy wrote:
> > From: Kumar Sanghvi <kumaras@chelsio.com>
> > 
> > Add support to add/remove flows for offload.  Following match
> > and action are supported for offloading a flow:
> > 
> > Match: ether-protocol, IPv4/IPv6 addresses, L4 ports (TCP/UDP)
> > Action: drop, redirect to another port on the device.
> > 
> > The qualifying flows can have accompanying mask information.
> > 
> > Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
> > Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
> > Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
> > ---

[...]

> > diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
> > index 45b5853ca2f1..07a4619e2164 100644
> > --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
> > +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
> > @@ -148,6 +148,32 @@ static int get_filter_steerq(struct net_device *dev,
> >  	return iq;
> >  }
> >  
> > +int cxgb4_get_free_ftid(struct net_device *dev, int family)
> > +{
> > +	struct adapter *adap = netdev2adap(dev);
> > +	struct tid_info *t = &adap->tids;
> > +	int ftid;
> > +
> > +	spin_lock_bh(&t->ftid_lock);
> > +	if (family == PF_INET) {
> > +		ftid = find_first_zero_bit(t->ftid_bmap, t->nftids);
> > +		if (ftid >= t->nftids)
> > +			ftid = -1;
> > +	} else {
> > +		ftid = bitmap_find_free_region(t->ftid_bmap, t->nftids, 2);
> > +		if (ftid < 0) {
> > +			ftid = -1;
> 
> ftid = -1 is not needed?

You are right, its not needed. Thank you for pointing this.
I will take care of this in V2.


> 
> > +			goto out_unlock;
> > +		}
> > +
> > +		/* this is only a lookup, keep the found region unallocated */
> > +		bitmap_release_region(t->ftid_bmap, ftid, 2);
> > +	}
> > +out_unlock:
> > +	spin_unlock_bh(&t->ftid_lock);
> > +	return ftid;
> > +}

[...]

> > diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
> > index 16dff71e4d02..1af01101faaf 100644
> > --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
> > +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
> > @@ -38,16 +38,292 @@
> >  #include "cxgb4.h"
> >  #include "cxgb4_tc_flower.h"
> > 

[...]

> >  int cxgb4_tc_flower_replace(struct net_device *dev,
> >  			    struct tc_cls_flower_offload *cls)
> >  {
> > -	return -EOPNOTSUPP;
> > +	struct adapter *adap = netdev2adap(dev);
> > +	struct ch_tc_flower_entry *ch_flower;
> > +	struct ch_filter_specification *fs;
> > +	struct filter_ctx ctx;
> > +	int fidx;
> > +	int ret;
> > +
> > +	if (cxgb4_validate_flow_actions(dev, cls))
> > +		return -EOPNOTSUPP;
> > +
> > +	if (cxgb4_validate_flow_match(dev, cls))
> > +		return -EOPNOTSUPP;
> > +
> > +	ch_flower = allocate_flower_entry();
> > +	if (!ch_flower) {
> > +		netdev_err(dev, "%s: ch_flower alloc failed.\n", __func__);
> > +		ret = -ENOMEM;
> > +		goto err;
> 
> Just return, err label is needed?

Yes, err label is not needed. I will take care of this in V2.

> 
> > +	}
> > +
> > +	fs = &ch_flower->fs;
> > +	fs->hitcnts = 1;
> > +	cxgb4_process_flow_actions(dev, cls, fs);
> > +	cxgb4_process_flow_match(dev, cls, fs);

[...]


> >  int cxgb4_tc_flower_destroy(struct net_device *dev,
> >  			    struct tc_cls_flower_offload *cls)
> >  {
> > -	return -EOPNOTSUPP;
> > +	struct adapter *adap = netdev2adap(dev);
> > +	struct ch_tc_flower_entry *ch_flower;
> > +	int ret;
> > +
> > +	ch_flower = ch_flower_lookup(adap, cls->cookie);
> > +	if (!ch_flower) {
> > +		ret = -ENOENT;
> > +		goto err;
> 
> Same as above

I will take care of this in V2.
Thank you.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-09-21 15:32 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-09-21  7:33 [PATCH net-next 0/4] cxgb4: add support to offload tc flower Rahul Lakkireddy
2017-09-21  7:33 ` [PATCH net-next 1/4] cxgb4: add tc flower offload skeleton Rahul Lakkireddy
2017-09-21  7:33 ` [PATCH net-next 2/4] cxgb4: add basic tc flower offload support Rahul Lakkireddy
2017-09-21 10:55   ` Yunsheng Lin
2017-09-21 15:31     ` Kumar Sanghvi
2017-09-21  7:33 ` [PATCH net-next 3/4] cxgb4: add support to offload action vlan Rahul Lakkireddy
2017-09-21  8:55   ` Jiri Pirko
2017-09-21 15:23     ` Kumar Sanghvi
2017-09-21  7:33 ` [PATCH net-next 4/4] cxgb4: fetch stats for offloaded tc flower flows Rahul Lakkireddy
2017-09-21  8:56 ` [PATCH net-next 0/4] cxgb4: add support to offload tc flower Jiri Pirko

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).