All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vinicius Costa Gomes <vinicius.gomes@intel.com>
To: intel-wired-lan@lists.osuosl.org
Cc: Vinicius Costa Gomes <vinicius.gomes@intel.com>,
	jeffrey.t.kirsher@intel.com, netdev@vger.kernel.org,
	jesus.sanchez-palencia@intel.com
Subject: [next-queue PATCH 7/8] igb: Add support for adding offloaded clsflower filters
Date: Fri, 23 Feb 2018 17:20:35 -0800	[thread overview]
Message-ID: <20180224012036.5834-8-vinicius.gomes@intel.com> (raw)
In-Reply-To: <20180224012036.5834-1-vinicius.gomes@intel.com>

This allows filters added by tc-flower and specifying MAC addresses,
Ethernet types, and the VLAN priority field, to be offloaded to the
controller.

This reuses most of the infrastructure used by ethtool, ethtool can be
used to read these filters, but modification and deletion can only be
done via tc-flower.

Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
---
 drivers/net/ethernet/intel/igb/igb.h         |   5 +
 drivers/net/ethernet/intel/igb/igb_ethtool.c |  13 ++-
 drivers/net/ethernet/intel/igb/igb_main.c    | 140 ++++++++++++++++++++++++++-
 3 files changed, 152 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index e06d6fdcb2ce..05d8c827d33e 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -463,6 +463,7 @@ struct igb_nfc_input {
 struct igb_nfc_filter {
 	struct hlist_node nfc_node;
 	struct igb_nfc_input filter;
+	unsigned long cookie;
 	u16 etype_reg_index;
 	u16 sw_idx;
 	u16 action;
@@ -747,4 +748,8 @@ int igb_add_mac_filter(struct igb_adapter *adapter, const u8 *addr,
 int igb_del_mac_filter(struct igb_adapter *adapter, const u8 *addr,
 		       const u8 queue, const u8 flags);
 
+int igb_update_ethtool_nfc_entry(struct igb_adapter *adapter,
+				 struct igb_nfc_filter *input,
+				 u16 sw_idx);
+
 #endif /* _IGB_H_ */
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index d8686a0f5b5d..5386eb68ab15 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -2918,9 +2918,9 @@ int igb_erase_filter(struct igb_adapter *adapter, struct igb_nfc_filter *input)
 	return 0;
 }
 
-static int igb_update_ethtool_nfc_entry(struct igb_adapter *adapter,
-					struct igb_nfc_filter *input,
-					u16 sw_idx)
+int igb_update_ethtool_nfc_entry(struct igb_adapter *adapter,
+				 struct igb_nfc_filter *input,
+				 u16 sw_idx)
 {
 	struct igb_nfc_filter *rule, *parent;
 	int err = -EINVAL;
@@ -2935,8 +2935,11 @@ static int igb_update_ethtool_nfc_entry(struct igb_adapter *adapter,
 		parent = rule;
 	}
 
-	/* if there is an old rule occupying our place remove it */
-	if (rule && (rule->sw_idx == sw_idx)) {
+	/* if there is an old rule occupying our place remove it, also
+	 * only allow rules added by ethtool to be removed, these
+	 * rules don't have a cookie
+	 */
+	if (rule && (!rule->cookie && rule->sw_idx == sw_idx)) {
 		if (!input)
 			err = igb_erase_filter(adapter, rule);
 
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 5344261e6f45..b1d401e77d62 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2497,10 +2497,148 @@ static int igb_offload_cbs(struct igb_adapter *adapter,
 	return 0;
 }
 
+#define ETHER_TYPE_FULL_MASK ((__force __be16)~0)
+
+static int igb_parse_cls_flower(struct igb_adapter *adapter,
+				struct tc_cls_flower_offload *f,
+				int traffic_class,
+				struct igb_nfc_filter *input)
+{
+	if (f->dissector->used_keys &
+	    ~(BIT(FLOW_DISSECTOR_KEY_BASIC) |
+	      BIT(FLOW_DISSECTOR_KEY_CONTROL) |
+	      BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
+	      BIT(FLOW_DISSECTOR_KEY_VLAN))) {
+		dev_err(&adapter->pdev->dev, "Unsupported key used: 0x%x\n",
+			f->dissector->used_keys);
+		return -EOPNOTSUPP;
+	}
+
+	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
+		struct flow_dissector_key_eth_addrs *key =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_ETH_ADDRS,
+						  f->key);
+
+		struct flow_dissector_key_eth_addrs *mask =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_ETH_ADDRS,
+						  f->mask);
+
+		if (is_broadcast_ether_addr(mask->dst)) {
+			input->filter.match_flags |=
+				IGB_FILTER_FLAG_DST_MAC_ADDR;
+			ether_addr_copy(input->filter.dst_addr, key->dst);
+		}
+
+		if (is_broadcast_ether_addr(mask->src)) {
+			input->filter.match_flags |=
+				IGB_FILTER_FLAG_SRC_MAC_ADDR;
+			ether_addr_copy(input->filter.src_addr, key->src);
+		}
+	}
+
+	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
+		struct flow_dissector_key_basic *key =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_BASIC,
+						  f->key);
+
+		struct flow_dissector_key_basic *mask =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_BASIC,
+						  f->mask);
+
+		if (mask->n_proto == ETHER_TYPE_FULL_MASK) {
+			input->filter.match_flags |=
+				IGB_FILTER_FLAG_ETHER_TYPE;
+			input->filter.etype = key->n_proto;
+		}
+	}
+
+	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
+		struct flow_dissector_key_vlan *key =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_VLAN,
+						  f->key);
+		struct flow_dissector_key_vlan *mask =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_VLAN,
+						  f->mask);
+
+		if (mask->vlan_priority) {
+			input->filter.match_flags |= IGB_FILTER_FLAG_VLAN_TCI;
+			input->filter.vlan_tci = key->vlan_priority;
+		}
+	}
+
+	input->action = traffic_class;
+	input->cookie = f->cookie;
+
+	return 0;
+}
+
 static int igb_configure_clsflower(struct igb_adapter *adapter,
 				   struct tc_cls_flower_offload *cls_flower)
 {
-	return -EOPNOTSUPP;
+	struct igb_nfc_filter *input, *rule;
+	u16 location = 0;
+	int err, tc;
+
+	if (!(adapter->netdev->hw_features & NETIF_F_NTUPLE))
+		return -EOPNOTSUPP;
+
+	tc = tc_classid_to_hwtc(adapter->netdev, cls_flower->classid);
+	if (tc < 0) {
+		dev_err(&adapter->pdev->dev, "Invalid traffic class\n");
+		return -EINVAL;
+	}
+
+	input = kzalloc(sizeof(*input), GFP_KERNEL);
+	if (!input)
+		return -ENOMEM;
+
+	err = igb_parse_cls_flower(adapter, cls_flower, tc, input);
+	if (err < 0)
+		goto error_parse;
+
+	spin_lock(&adapter->nfc_lock);
+
+	hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node) {
+		if (!memcmp(&input->filter, &rule->filter,
+			    sizeof(input->filter))) {
+			err = -EEXIST;
+			dev_err(&adapter->pdev->dev,
+				"tc-flower: this filter is already set\n");
+			goto error_locked;
+		}
+
+		if (rule->sw_idx > location)
+			location = rule->sw_idx;
+	}
+
+	if (adapter->nfc_filter_count != 0)
+		location++;
+
+	input->sw_idx = location;
+
+	err = igb_add_filter(adapter, input);
+	if (err < 0)
+		goto error_locked;
+
+	igb_update_ethtool_nfc_entry(adapter, input, location);
+
+	spin_unlock(&adapter->nfc_lock);
+
+	return 0;
+
+error_locked:
+	spin_unlock(&adapter->nfc_lock);
+
+error_parse:
+	kfree(input);
+
+	return err;
 }
 
 static int igb_delete_clsflower(struct igb_adapter *adapter,
-- 
2.16.2

WARNING: multiple messages have this Message-ID (diff)
From: Vinicius Costa Gomes <vinicius.gomes@intel.com>
To: intel-wired-lan@osuosl.org
Subject: [Intel-wired-lan] [next-queue PATCH 7/8] igb: Add support for adding offloaded clsflower filters
Date: Fri, 23 Feb 2018 17:20:35 -0800	[thread overview]
Message-ID: <20180224012036.5834-8-vinicius.gomes@intel.com> (raw)
In-Reply-To: <20180224012036.5834-1-vinicius.gomes@intel.com>

This allows filters added by tc-flower and specifying MAC addresses,
Ethernet types, and the VLAN priority field, to be offloaded to the
controller.

This reuses most of the infrastructure used by ethtool, ethtool can be
used to read these filters, but modification and deletion can only be
done via tc-flower.

Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
---
 drivers/net/ethernet/intel/igb/igb.h         |   5 +
 drivers/net/ethernet/intel/igb/igb_ethtool.c |  13 ++-
 drivers/net/ethernet/intel/igb/igb_main.c    | 140 ++++++++++++++++++++++++++-
 3 files changed, 152 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index e06d6fdcb2ce..05d8c827d33e 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -463,6 +463,7 @@ struct igb_nfc_input {
 struct igb_nfc_filter {
 	struct hlist_node nfc_node;
 	struct igb_nfc_input filter;
+	unsigned long cookie;
 	u16 etype_reg_index;
 	u16 sw_idx;
 	u16 action;
@@ -747,4 +748,8 @@ int igb_add_mac_filter(struct igb_adapter *adapter, const u8 *addr,
 int igb_del_mac_filter(struct igb_adapter *adapter, const u8 *addr,
 		       const u8 queue, const u8 flags);
 
+int igb_update_ethtool_nfc_entry(struct igb_adapter *adapter,
+				 struct igb_nfc_filter *input,
+				 u16 sw_idx);
+
 #endif /* _IGB_H_ */
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index d8686a0f5b5d..5386eb68ab15 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -2918,9 +2918,9 @@ int igb_erase_filter(struct igb_adapter *adapter, struct igb_nfc_filter *input)
 	return 0;
 }
 
-static int igb_update_ethtool_nfc_entry(struct igb_adapter *adapter,
-					struct igb_nfc_filter *input,
-					u16 sw_idx)
+int igb_update_ethtool_nfc_entry(struct igb_adapter *adapter,
+				 struct igb_nfc_filter *input,
+				 u16 sw_idx)
 {
 	struct igb_nfc_filter *rule, *parent;
 	int err = -EINVAL;
@@ -2935,8 +2935,11 @@ static int igb_update_ethtool_nfc_entry(struct igb_adapter *adapter,
 		parent = rule;
 	}
 
-	/* if there is an old rule occupying our place remove it */
-	if (rule && (rule->sw_idx == sw_idx)) {
+	/* if there is an old rule occupying our place remove it, also
+	 * only allow rules added by ethtool to be removed, these
+	 * rules don't have a cookie
+	 */
+	if (rule && (!rule->cookie && rule->sw_idx == sw_idx)) {
 		if (!input)
 			err = igb_erase_filter(adapter, rule);
 
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 5344261e6f45..b1d401e77d62 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2497,10 +2497,148 @@ static int igb_offload_cbs(struct igb_adapter *adapter,
 	return 0;
 }
 
+#define ETHER_TYPE_FULL_MASK ((__force __be16)~0)
+
+static int igb_parse_cls_flower(struct igb_adapter *adapter,
+				struct tc_cls_flower_offload *f,
+				int traffic_class,
+				struct igb_nfc_filter *input)
+{
+	if (f->dissector->used_keys &
+	    ~(BIT(FLOW_DISSECTOR_KEY_BASIC) |
+	      BIT(FLOW_DISSECTOR_KEY_CONTROL) |
+	      BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
+	      BIT(FLOW_DISSECTOR_KEY_VLAN))) {
+		dev_err(&adapter->pdev->dev, "Unsupported key used: 0x%x\n",
+			f->dissector->used_keys);
+		return -EOPNOTSUPP;
+	}
+
+	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
+		struct flow_dissector_key_eth_addrs *key =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_ETH_ADDRS,
+						  f->key);
+
+		struct flow_dissector_key_eth_addrs *mask =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_ETH_ADDRS,
+						  f->mask);
+
+		if (is_broadcast_ether_addr(mask->dst)) {
+			input->filter.match_flags |=
+				IGB_FILTER_FLAG_DST_MAC_ADDR;
+			ether_addr_copy(input->filter.dst_addr, key->dst);
+		}
+
+		if (is_broadcast_ether_addr(mask->src)) {
+			input->filter.match_flags |=
+				IGB_FILTER_FLAG_SRC_MAC_ADDR;
+			ether_addr_copy(input->filter.src_addr, key->src);
+		}
+	}
+
+	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
+		struct flow_dissector_key_basic *key =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_BASIC,
+						  f->key);
+
+		struct flow_dissector_key_basic *mask =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_BASIC,
+						  f->mask);
+
+		if (mask->n_proto == ETHER_TYPE_FULL_MASK) {
+			input->filter.match_flags |=
+				IGB_FILTER_FLAG_ETHER_TYPE;
+			input->filter.etype = key->n_proto;
+		}
+	}
+
+	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
+		struct flow_dissector_key_vlan *key =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_VLAN,
+						  f->key);
+		struct flow_dissector_key_vlan *mask =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_VLAN,
+						  f->mask);
+
+		if (mask->vlan_priority) {
+			input->filter.match_flags |= IGB_FILTER_FLAG_VLAN_TCI;
+			input->filter.vlan_tci = key->vlan_priority;
+		}
+	}
+
+	input->action = traffic_class;
+	input->cookie = f->cookie;
+
+	return 0;
+}
+
 static int igb_configure_clsflower(struct igb_adapter *adapter,
 				   struct tc_cls_flower_offload *cls_flower)
 {
-	return -EOPNOTSUPP;
+	struct igb_nfc_filter *input, *rule;
+	u16 location = 0;
+	int err, tc;
+
+	if (!(adapter->netdev->hw_features & NETIF_F_NTUPLE))
+		return -EOPNOTSUPP;
+
+	tc = tc_classid_to_hwtc(adapter->netdev, cls_flower->classid);
+	if (tc < 0) {
+		dev_err(&adapter->pdev->dev, "Invalid traffic class\n");
+		return -EINVAL;
+	}
+
+	input = kzalloc(sizeof(*input), GFP_KERNEL);
+	if (!input)
+		return -ENOMEM;
+
+	err = igb_parse_cls_flower(adapter, cls_flower, tc, input);
+	if (err < 0)
+		goto error_parse;
+
+	spin_lock(&adapter->nfc_lock);
+
+	hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node) {
+		if (!memcmp(&input->filter, &rule->filter,
+			    sizeof(input->filter))) {
+			err = -EEXIST;
+			dev_err(&adapter->pdev->dev,
+				"tc-flower: this filter is already set\n");
+			goto error_locked;
+		}
+
+		if (rule->sw_idx > location)
+			location = rule->sw_idx;
+	}
+
+	if (adapter->nfc_filter_count != 0)
+		location++;
+
+	input->sw_idx = location;
+
+	err = igb_add_filter(adapter, input);
+	if (err < 0)
+		goto error_locked;
+
+	igb_update_ethtool_nfc_entry(adapter, input, location);
+
+	spin_unlock(&adapter->nfc_lock);
+
+	return 0;
+
+error_locked:
+	spin_unlock(&adapter->nfc_lock);
+
+error_parse:
+	kfree(input);
+
+	return err;
 }
 
 static int igb_delete_clsflower(struct igb_adapter *adapter,
-- 
2.16.2


  parent reply	other threads:[~2018-02-24  1:21 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-24  1:20 [next-queue PATCH 0/8] igb: offloading of receive filters Vinicius Costa Gomes
2018-02-24  1:20 ` [Intel-wired-lan] " Vinicius Costa Gomes
2018-02-24  1:20 ` [next-queue PATCH 1/8] igb: Fix not adding filter elements to the list Vinicius Costa Gomes
2018-02-24  1:20   ` [Intel-wired-lan] " Vinicius Costa Gomes
2018-02-24  1:20 ` [next-queue PATCH 2/8] igb: Fix queue selection on MAC filters on i210 and i211 Vinicius Costa Gomes
2018-02-24  1:20   ` [Intel-wired-lan] " Vinicius Costa Gomes
2018-02-24  1:20 ` [next-queue PATCH 3/8] igb: Enable the hardware traffic class feature bit for igb models Vinicius Costa Gomes
2018-02-24  1:20   ` [Intel-wired-lan] " Vinicius Costa Gomes
2018-02-25 22:37   ` Alexander Duyck
2018-02-25 22:37     ` Alexander Duyck
2018-02-26 18:49     ` Vinicius Costa Gomes
2018-02-26 18:49       ` Vinicius Costa Gomes
2018-02-24  1:20 ` [next-queue PATCH 4/8] igb: Add support for MAC address filters specifying source addresses Vinicius Costa Gomes
2018-02-24  1:20   ` [Intel-wired-lan] " Vinicius Costa Gomes
2018-02-25 22:42   ` Alexander Duyck
2018-02-25 22:42     ` Alexander Duyck
2018-02-26 19:24     ` Vinicius Costa Gomes
2018-02-26 19:24       ` Vinicius Costa Gomes
2018-02-24  1:20 ` [next-queue PATCH 5/8] igb: Add support for ethtool MAC address filters Vinicius Costa Gomes
2018-02-24  1:20   ` [Intel-wired-lan] " Vinicius Costa Gomes
2018-02-24  4:38   ` Florian Fainelli
2018-02-24  4:38     ` [Intel-wired-lan] " Florian Fainelli
2018-02-26 19:30     ` Vinicius Costa Gomes
2018-02-26 19:30       ` [Intel-wired-lan] " Vinicius Costa Gomes
2018-02-24  1:20 ` [next-queue PATCH 6/8] igb: Add the skeletons for tc-flower offloading Vinicius Costa Gomes
2018-02-24  1:20   ` [Intel-wired-lan] " Vinicius Costa Gomes
2018-02-24  1:20 ` Vinicius Costa Gomes [this message]
2018-02-24  1:20   ` [Intel-wired-lan] [next-queue PATCH 7/8] igb: Add support for adding offloaded clsflower filters Vinicius Costa Gomes
2018-02-24  4:45   ` Florian Fainelli
2018-02-24  4:45     ` [Intel-wired-lan] " Florian Fainelli
2018-02-27  0:40     ` Vinicius Costa Gomes
2018-02-27  0:40       ` [Intel-wired-lan] " Vinicius Costa Gomes
2018-02-27  0:51       ` Florian Fainelli
2018-02-27  0:51         ` [Intel-wired-lan] " Florian Fainelli
2018-02-27  1:51         ` Vinicius Costa Gomes
2018-02-27  1:51           ` [Intel-wired-lan] " Vinicius Costa Gomes
2018-02-26  0:12   ` kbuild test robot
2018-02-26  0:12     ` kbuild test robot
2018-02-24  1:20 ` [next-queue PATCH 8/8] igb: Add support for removing offloaded tc-flower filters Vinicius Costa Gomes
2018-02-24  1:20   ` [Intel-wired-lan] " Vinicius Costa Gomes
2018-02-24  4:36   ` Florian Fainelli
2018-02-24  4:36     ` [Intel-wired-lan] " Florian Fainelli
2018-02-26 20:59     ` Vinicius Costa Gomes
2018-02-26 20:59       ` [Intel-wired-lan] " Vinicius Costa Gomes

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=20180224012036.5834-8-vinicius.gomes@intel.com \
    --to=vinicius.gomes@intel.com \
    --cc=intel-wired-lan@lists.osuosl.org \
    --cc=jeffrey.t.kirsher@intel.com \
    --cc=jesus.sanchez-palencia@intel.com \
    --cc=netdev@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.