* [net-next-2.6 PATCH 00/10] Workarounds and fixes for ntuple filters
@ 2011-02-25 23:32 Alexander Duyck
2011-02-25 23:32 ` [net-next-2.6 PATCH 01/10] ethtool: prevent null pointer dereference with NTUPLE set but no set_rx_ntuple Alexander Duyck
` (9 more replies)
0 siblings, 10 replies; 24+ messages in thread
From: Alexander Duyck @ 2011-02-25 23:32 UTC (permalink / raw)
To: davem, jeffrey.t.kirsher, bhutchings; +Cc: netdev
This patch series is meant to address issue in the implementation of ntuple
filters in both ixgbe and the kernel. The main issue being that ntuple
filters didn't support the ability for drivers to retain and display
filters.
This series addresses it by removing the ETHTOOL_GRXNTUPLE interface
from the kernel and extends the ethtool network flow classifier interface
to handle the same fields that ntuple filters provide. I have a separate
set of patches I will be emailing out in the next few minutes that will
contain the ethtool user-space portion of these changes.
The patches labeled with RFC are currently just for comments as I am not
submitting them directly to the netdev tree and will be instead submitting
them to the Jeff Kirsher's Intel network driver tree for submission.
---
Alexander Duyck (10):
[RFC] ixgbe: Add support for using the same fields as ntuple in nfc
[RFC] ixgbe: add support for nfc addition and removal of filters
[RFC] ixgbe: add support for displaying ntuple filters via the nfc interface
[RFC] ixgbe: add basic support for settting and getting nfc controls
[RFC] ixgbe: update perfect filter framework to support retaining filters
[RFC] ixgbe: add support for different Rx packet buffer sizes
[RFC] ethtool: remove support for ETHTOOL_GRXNTUPLE
[RFC] ixgbe: remove ntuple filtering
ethtool: add ntuple flow specifier to network flow classifier
ethtool: prevent null pointer dereference with NTUPLE set but no set_rx_ntuple
drivers/net/ixgbe/ixgbe.h | 29 +-
drivers/net/ixgbe/ixgbe_82598.c | 2
drivers/net/ixgbe/ixgbe_82599.c | 661 ++++++++++++++++++++-----------------
drivers/net/ixgbe/ixgbe_dcb_nl.c | 47 +--
drivers/net/ixgbe/ixgbe_ethtool.c | 504 ++++++++++++++++++++++------
drivers/net/ixgbe/ixgbe_main.c | 90 +++--
drivers/net/ixgbe/ixgbe_type.h | 25 +
drivers/net/ixgbe/ixgbe_x540.c | 2
include/linux/ethtool.h | 27 +-
include/linux/netdevice.h | 3
net/core/dev.c | 5
net/core/ethtool.c | 302 -----------------
12 files changed, 884 insertions(+), 813 deletions(-)
--
^ permalink raw reply [flat|nested] 24+ messages in thread
* [net-next-2.6 PATCH 01/10] ethtool: prevent null pointer dereference with NTUPLE set but no set_rx_ntuple
2011-02-25 23:32 [net-next-2.6 PATCH 00/10] Workarounds and fixes for ntuple filters Alexander Duyck
@ 2011-02-25 23:32 ` Alexander Duyck
2011-02-26 0:21 ` Ben Hutchings
2011-02-25 23:32 ` [net-next-2.6 PATCH 02/10] ethtool: add ntuple flow specifier to network flow classifier Alexander Duyck
` (8 subsequent siblings)
9 siblings, 1 reply; 24+ messages in thread
From: Alexander Duyck @ 2011-02-25 23:32 UTC (permalink / raw)
To: davem, jeffrey.t.kirsher, bhutchings; +Cc: netdev
This change is meant to prevent a possible null pointer dereference if
NETIF_F_NTUPLE is defined but the set_rx_ntuple function pointer is not.
This issue appears to affect all kernels since 2.6.34.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---
net/core/ethtool.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index c1a71bb..4843674 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -893,6 +893,9 @@ static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev,
struct ethtool_rx_ntuple_flow_spec_container *fsc = NULL;
int ret;
+ if (!ops->set_rx_ntuple)
+ return -EOPNOTSUPP;
+
if (!(dev->features & NETIF_F_NTUPLE))
return -EINVAL;
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [net-next-2.6 PATCH 02/10] ethtool: add ntuple flow specifier to network flow classifier
2011-02-25 23:32 [net-next-2.6 PATCH 00/10] Workarounds and fixes for ntuple filters Alexander Duyck
2011-02-25 23:32 ` [net-next-2.6 PATCH 01/10] ethtool: prevent null pointer dereference with NTUPLE set but no set_rx_ntuple Alexander Duyck
@ 2011-02-25 23:32 ` Alexander Duyck
2011-02-26 1:00 ` Ben Hutchings
2011-02-27 0:05 ` David Miller
2011-02-25 23:32 ` [net-next-2.6 PATCH 03/10] [RFC] ixgbe: remove ntuple filtering Alexander Duyck
` (7 subsequent siblings)
9 siblings, 2 replies; 24+ messages in thread
From: Alexander Duyck @ 2011-02-25 23:32 UTC (permalink / raw)
To: davem, jeffrey.t.kirsher, bhutchings; +Cc: netdev
This change is meant to add an ntuple define type to the rx network flow
classification specifiers. The idea is to allow ntuple to be displayed and
possibly configured via the network flow classification interface. To do
this I added a ntuple_flow_spec_ext to the lsit of supported filters, and
added a flow_type_ext value to the structure in an unused hole within the
ethtool_rx_flow_spec structure.
Due to the fact that the flow specifier structures are only 4 byte aligned
instead of 8 I had to break the user data field into 2 sections. In
addition I added the vlan ethertype field since this is what ixgbe was
using the user-data for currently and it allows for the fields to stay 4
byte aligned while occupying space at the end of the flow_spec.
In order to guarantee byte ordering I also thought it best to keep all
fields in the flow_spec area a big endian value, as such I added vlan, vlan
ethertype, and data as big endian values.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---
include/linux/ethtool.h | 20 ++++++++++++++++++++
1 files changed, 20 insertions(+), 0 deletions(-)
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index aac3e2e..3d1f8e0 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -378,10 +378,25 @@ struct ethtool_usrip4_spec {
};
/**
+ * struct ethtool_ntuple_spec_ext - flow spec extension for ntuple in nfc
+ * @unused: space unused by extension
+ * @vlan_etype: EtherType for vlan tagged packet to match
+ * @vlan_tci: VLAN tag to match
+ * @data: Driver-dependent data to match
+ */
+struct ethtool_ntuple_spec_ext {
+ __be32 unused[15];
+ __be16 vlan_etype;
+ __be16 vlan_tci;
+ __be32 data[2];
+};
+
+/**
* struct ethtool_rx_flow_spec - specification for RX flow filter
* @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW
* @h_u: Flow fields to match (dependent on @flow_type)
* @m_u: Masks for flow field bits to be ignored
+ * @flow_type_ext: Type of extended match to perform, e.g. %NTUPLE_FLOW_EXT
* @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC
* if packets should be discarded
* @location: Index of filter in hardware table
@@ -396,8 +411,10 @@ struct ethtool_rx_flow_spec {
struct ethtool_ah_espip4_spec esp_ip4_spec;
struct ethtool_usrip4_spec usr_ip4_spec;
struct ethhdr ether_spec;
+ struct ethtool_ntuple_spec_ext ntuple_spec;
__u8 hdata[72];
} h_u, m_u;
+ __u32 flow_type_ext;
__u64 ring_cookie;
__u32 location;
};
@@ -955,6 +972,9 @@ struct ethtool_ops {
#define IPV6_FLOW 0x11 /* hash only */
#define ETHER_FLOW 0x12 /* spec only (ether_spec) */
+/* Flow extension types for network flow classifier */
+#define NTUPLE_FLOW_EXT 0x01 /* indicates ntuple in nfc */
+
/* L3-L4 network traffic flow hash options */
#define RXH_L2DA (1 << 1)
#define RXH_VLAN (1 << 2)
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [net-next-2.6 PATCH 03/10] [RFC] ixgbe: remove ntuple filtering
2011-02-25 23:32 [net-next-2.6 PATCH 00/10] Workarounds and fixes for ntuple filters Alexander Duyck
2011-02-25 23:32 ` [net-next-2.6 PATCH 01/10] ethtool: prevent null pointer dereference with NTUPLE set but no set_rx_ntuple Alexander Duyck
2011-02-25 23:32 ` [net-next-2.6 PATCH 02/10] ethtool: add ntuple flow specifier to network flow classifier Alexander Duyck
@ 2011-02-25 23:32 ` Alexander Duyck
2011-02-25 23:33 ` [net-next-2.6 PATCH 04/10] [RFC] ethtool: remove support for ETHTOOL_GRXNTUPLE Alexander Duyck
` (6 subsequent siblings)
9 siblings, 0 replies; 24+ messages in thread
From: Alexander Duyck @ 2011-02-25 23:32 UTC (permalink / raw)
To: davem, jeffrey.t.kirsher, bhutchings; +Cc: netdev
Due to numerous issues in ntuple filters it has been decieded to move the
interface over to the network flow classification interface. As a first
step to achieving this I first need to remove the old ntuple interface.
In addition I am removing the requirement that ntuple filters have the same
number of queues and requirements as ATR. As a result this change will
make it so that all the ntuple flag does is disable ATR for now.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---
drivers/net/ixgbe/ixgbe_dcb_nl.c | 47 +++++------
drivers/net/ixgbe/ixgbe_ethtool.c | 162 +++----------------------------------
drivers/net/ixgbe/ixgbe_main.c | 45 +++-------
3 files changed, 48 insertions(+), 206 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c
index a977df3..47fd9f6 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c
@@ -114,11 +114,12 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
u8 err = 0;
struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ /* verify there is something to do, if not then exit */
+ if (!!state != !(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
+ return err;
+
if (state > 0) {
/* Turn on DCB */
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
- goto out;
-
if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
e_err(drv, "Enable failed, needs MSI-X\n");
err = 1;
@@ -138,7 +139,6 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
- adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
break;
default:
break;
@@ -150,29 +150,28 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
netdev->netdev_ops->ndo_open(netdev);
} else {
/* Turn off DCB */
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
- if (netif_running(netdev))
- netdev->netdev_ops->ndo_stop(netdev);
- ixgbe_clear_interrupt_scheme(adapter);
+ if (netif_running(netdev))
+ netdev->netdev_ops->ndo_stop(netdev);
+ ixgbe_clear_interrupt_scheme(adapter);
- adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
- adapter->temp_dcb_cfg.pfc_mode_enable = false;
- adapter->dcb_cfg.pfc_mode_enable = false;
- adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
- adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
- switch (adapter->hw.mac.type) {
- case ixgbe_mac_82599EB:
- case ixgbe_mac_X540:
+ adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
+ adapter->temp_dcb_cfg.pfc_mode_enable = false;
+ adapter->dcb_cfg.pfc_mode_enable = false;
+ adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
+ adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_82599EB:
+ case ixgbe_mac_X540:
+ if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
- break;
- default:
- break;
- }
-
- ixgbe_init_interrupt_scheme(adapter);
- if (netif_running(netdev))
- netdev->netdev_ops->ndo_open(netdev);
+ break;
+ default:
+ break;
}
+
+ ixgbe_init_interrupt_scheme(adapter);
+ if (netif_running(netdev))
+ netdev->netdev_ops->ndo_open(netdev);
}
out:
return err;
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 309272f..1b40c02 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -1031,9 +1031,6 @@ static int ixgbe_get_sset_count(struct net_device *netdev, int sset)
return IXGBE_TEST_LEN;
case ETH_SS_STATS:
return IXGBE_STATS_LEN;
- case ETH_SS_NTUPLE_FILTERS:
- return ETHTOOL_MAX_NTUPLE_LIST_ENTRY *
- ETHTOOL_MAX_NTUPLE_STRING_PER_ENTRY;
default:
return -EOPNOTSUPP;
}
@@ -2277,20 +2274,19 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
* Check if Flow Director n-tuple support was enabled or disabled. If
* the state changed, we need to reset.
*/
- if ((adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) &&
- (!(data & ETH_FLAG_NTUPLE))) {
- /* turn off Flow Director perfect, set hash and reset */
+ if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) {
+ /* turn off ATR, enable perfect filters and reset */
+ if (data & ETH_FLAG_NTUPLE) {
+ adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
+ adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
+ need_reset = true;
+ }
+ } else if (!(data & ETH_FLAG_NTUPLE)) {
+ /* turn off Flow Director, set ATR and reset */
adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
- adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
- need_reset = true;
- } else if ((!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) &&
- (data & ETH_FLAG_NTUPLE)) {
- /* turn off Flow Director hash, enable perfect and reset */
- adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
- adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
+ if (adapter->flags & IXGBE_FLAG_RSS_ENABLED)
+ adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
need_reset = true;
- } else {
- /* no state change */
}
if (need_reset) {
@@ -2303,141 +2299,6 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
return 0;
}
-static int ixgbe_set_rx_ntuple(struct net_device *dev,
- struct ethtool_rx_ntuple *cmd)
-{
- struct ixgbe_adapter *adapter = netdev_priv(dev);
- struct ethtool_rx_ntuple_flow_spec *fs = &cmd->fs;
- union ixgbe_atr_input input_struct;
- struct ixgbe_atr_input_masks input_masks;
- int target_queue;
- int err;
-
- if (adapter->hw.mac.type == ixgbe_mac_82598EB)
- return -EOPNOTSUPP;
-
- /*
- * Don't allow programming if the action is a queue greater than
- * the number of online Tx queues.
- */
- if ((fs->action >= adapter->num_tx_queues) ||
- (fs->action < ETHTOOL_RXNTUPLE_ACTION_DROP))
- return -EINVAL;
-
- memset(&input_struct, 0, sizeof(union ixgbe_atr_input));
- memset(&input_masks, 0, sizeof(struct ixgbe_atr_input_masks));
-
- /* record flow type */
- switch (fs->flow_type) {
- case IPV4_FLOW:
- input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_IPV4;
- break;
- case TCP_V4_FLOW:
- input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
- break;
- case UDP_V4_FLOW:
- input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
- break;
- case SCTP_V4_FLOW:
- input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
- break;
- default:
- return -1;
- }
-
- /* copy vlan tag minus the CFI bit */
- if ((fs->vlan_tag & 0xEFFF) || (~fs->vlan_tag_mask & 0xEFFF)) {
- input_struct.formatted.vlan_id = htons(fs->vlan_tag & 0xEFFF);
- if (!fs->vlan_tag_mask) {
- input_masks.vlan_id_mask = htons(0xEFFF);
- } else {
- switch (~fs->vlan_tag_mask & 0xEFFF) {
- /* all of these are valid vlan-mask values */
- case 0xEFFF:
- case 0xE000:
- case 0x0FFF:
- case 0x0000:
- input_masks.vlan_id_mask =
- htons(~fs->vlan_tag_mask);
- break;
- /* exit with error if vlan-mask is invalid */
- default:
- e_err(drv, "Partial VLAN ID or "
- "priority mask in vlan-mask is not "
- "supported by hardware\n");
- return -1;
- }
- }
- }
-
- /* make sure we only use the first 2 bytes of user data */
- if ((fs->data & 0xFFFF) || (~fs->data_mask & 0xFFFF)) {
- input_struct.formatted.flex_bytes = htons(fs->data & 0xFFFF);
- if (!(fs->data_mask & 0xFFFF)) {
- input_masks.flex_mask = 0xFFFF;
- } else if (~fs->data_mask & 0xFFFF) {
- e_err(drv, "Partial user-def-mask is not "
- "supported by hardware\n");
- return -1;
- }
- }
-
- /*
- * Copy input into formatted structures
- *
- * These assignments are based on the following logic
- * If neither input or mask are set assume value is masked out.
- * If input is set, but mask is not mask should default to accept all.
- * If input is not set, but mask is set then mask likely results in 0.
- * If input is set and mask is set then assign both.
- */
- if (fs->h_u.tcp_ip4_spec.ip4src || ~fs->m_u.tcp_ip4_spec.ip4src) {
- input_struct.formatted.src_ip[0] = fs->h_u.tcp_ip4_spec.ip4src;
- if (!fs->m_u.tcp_ip4_spec.ip4src)
- input_masks.src_ip_mask[0] = 0xFFFFFFFF;
- else
- input_masks.src_ip_mask[0] =
- ~fs->m_u.tcp_ip4_spec.ip4src;
- }
- if (fs->h_u.tcp_ip4_spec.ip4dst || ~fs->m_u.tcp_ip4_spec.ip4dst) {
- input_struct.formatted.dst_ip[0] = fs->h_u.tcp_ip4_spec.ip4dst;
- if (!fs->m_u.tcp_ip4_spec.ip4dst)
- input_masks.dst_ip_mask[0] = 0xFFFFFFFF;
- else
- input_masks.dst_ip_mask[0] =
- ~fs->m_u.tcp_ip4_spec.ip4dst;
- }
- if (fs->h_u.tcp_ip4_spec.psrc || ~fs->m_u.tcp_ip4_spec.psrc) {
- input_struct.formatted.src_port = fs->h_u.tcp_ip4_spec.psrc;
- if (!fs->m_u.tcp_ip4_spec.psrc)
- input_masks.src_port_mask = 0xFFFF;
- else
- input_masks.src_port_mask = ~fs->m_u.tcp_ip4_spec.psrc;
- }
- if (fs->h_u.tcp_ip4_spec.pdst || ~fs->m_u.tcp_ip4_spec.pdst) {
- input_struct.formatted.dst_port = fs->h_u.tcp_ip4_spec.pdst;
- if (!fs->m_u.tcp_ip4_spec.pdst)
- input_masks.dst_port_mask = 0xFFFF;
- else
- input_masks.dst_port_mask = ~fs->m_u.tcp_ip4_spec.pdst;
- }
-
- /* determine if we need to drop or route the packet */
- if (fs->action == ETHTOOL_RXNTUPLE_ACTION_DROP)
- target_queue = MAX_RX_QUEUES - 1;
- else
- target_queue = fs->action;
-
- spin_lock(&adapter->fdir_perfect_lock);
- err = ixgbe_fdir_add_perfect_filter_82599(&adapter->hw,
- &input_struct,
- &input_masks, 0,
- target_queue);
- spin_unlock(&adapter->fdir_perfect_lock);
-
- return err ? -1 : 0;
-}
-
static const struct ethtool_ops ixgbe_ethtool_ops = {
.get_settings = ixgbe_get_settings,
.set_settings = ixgbe_set_settings,
@@ -2473,7 +2334,6 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
.set_coalesce = ixgbe_set_coalesce,
.get_flags = ethtool_op_get_flags,
.set_flags = ixgbe_set_flags,
- .set_rx_ntuple = ixgbe_set_rx_ntuple,
};
void ixgbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index f0d0c5a..929f059 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -1568,9 +1568,8 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
q_vector->eitr = adapter->rx_eitr_param;
ixgbe_write_eitr(q_vector);
- /* If Flow Director is enabled, set interrupt affinity */
- if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
- (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) {
+ /* If ATR is enabled, set interrupt affinity */
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
/*
* Allocate the affinity_hint cpumask, assign the mask
* for this vector, and set our affinity_hint for
@@ -2453,8 +2452,7 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
default:
break;
}
- if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
- adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
mask |= IXGBE_EIMS_FLOW_DIR;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
@@ -3692,8 +3690,6 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
adapter->tx_ring[i]->atr_sample_rate =
adapter->atr_sample_rate;
ixgbe_init_fdir_signature_82599(hw, adapter->fdir_pballoc);
- } else if (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) {
- ixgbe_init_fdir_perfect_82599(hw, adapter->fdir_pballoc);
}
ixgbe_configure_virtualization(adapter);
@@ -4138,8 +4134,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
free_cpumask_var(q_vector->affinity_mask);
}
- if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
- adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
cancel_work_sync(&adapter->fdir_reinit_task);
if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
@@ -4164,9 +4159,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
break;
}
- /* clear n-tuple filters that are cached */
- ethtool_ntuple_flush(netdev);
-
if (!pci_channel_offline(adapter->pdev))
ixgbe_reset(adapter);
@@ -4313,15 +4305,13 @@ static inline bool ixgbe_set_fdir_queues(struct ixgbe_adapter *adapter)
f_fdir->mask = 0;
/* Flow Director must have RSS enabled */
- if (adapter->flags & IXGBE_FLAG_RSS_ENABLED &&
- ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
- (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)))) {
+ if ((adapter->flags & IXGBE_FLAG_RSS_ENABLED) &&
+ (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)) {
adapter->num_tx_queues = f_fdir->indices;
adapter->num_rx_queues = f_fdir->indices;
ret = true;
} else {
adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
- adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
}
return ret;
}
@@ -4354,8 +4344,7 @@ static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter)
#endif
if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
e_info(probe, "FCoE enabled with RSS\n");
- if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
- (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
ixgbe_set_fdir_queues(adapter);
else
ixgbe_set_rss_queues(adapter);
@@ -4598,9 +4587,8 @@ static inline bool ixgbe_cache_ring_fdir(struct ixgbe_adapter *adapter)
int i;
bool ret = false;
- if (adapter->flags & IXGBE_FLAG_RSS_ENABLED &&
- ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
- (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))) {
+ if ((adapter->flags & IXGBE_FLAG_RSS_ENABLED) &&
+ (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)) {
for (i = 0; i < adapter->num_rx_queues; i++)
adapter->rx_ring[i]->reg_idx = i;
for (i = 0; i < adapter->num_tx_queues; i++)
@@ -4656,8 +4644,7 @@ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter)
}
#endif /* CONFIG_IXGBE_DCB */
if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
- if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
- (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
ixgbe_cache_ring_fdir(adapter);
else
ixgbe_cache_ring_rss(adapter);
@@ -4837,14 +4824,12 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter)
adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
- if (adapter->flags & (IXGBE_FLAG_FDIR_HASH_CAPABLE |
- IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) {
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
e_err(probe,
- "Flow Director is not supported while multiple "
+ "ATR is not supported while multiple "
"queues are disabled. Disabling Flow Director\n");
}
adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
- adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
adapter->atr_sample_rate = 0;
if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
ixgbe_disable_sriov(adapter);
@@ -7446,8 +7431,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
/* carrier off reporting is important to ethtool even BEFORE open */
netif_carrier_off(netdev);
- if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
- adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
INIT_WORK(&adapter->fdir_reinit_task, ixgbe_fdir_reinit_task);
if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
@@ -7524,8 +7508,7 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
cancel_work_sync(&adapter->sfp_task);
cancel_work_sync(&adapter->multispeed_fiber_task);
cancel_work_sync(&adapter->sfp_config_module_task);
- if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
- adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
cancel_work_sync(&adapter->fdir_reinit_task);
if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
cancel_work_sync(&adapter->check_overtemp_task);
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [net-next-2.6 PATCH 04/10] [RFC] ethtool: remove support for ETHTOOL_GRXNTUPLE
2011-02-25 23:32 [net-next-2.6 PATCH 00/10] Workarounds and fixes for ntuple filters Alexander Duyck
` (2 preceding siblings ...)
2011-02-25 23:32 ` [net-next-2.6 PATCH 03/10] [RFC] ixgbe: remove ntuple filtering Alexander Duyck
@ 2011-02-25 23:33 ` Alexander Duyck
2011-02-25 23:33 ` [net-next-2.6 PATCH 05/10] [RFC] ixgbe: add support for different Rx packet buffer sizes Alexander Duyck
` (5 subsequent siblings)
9 siblings, 0 replies; 24+ messages in thread
From: Alexander Duyck @ 2011-02-25 23:33 UTC (permalink / raw)
To: davem, jeffrey.t.kirsher, bhutchings; +Cc: netdev
This change is meant to remove all support for displaying an ntuple as
strings via ETHTOOL_GRXNTUPLE. The reason for this change is due to the
fact that multiple issues have been found including:
- Multiple buffer overruns for strings being displayed.
- Incorrect filters displayed, cleared filters with ring of -2 are displayed
- Setting get_rx_ntuple displays no rules if defined.
- Endianess wrong on displayed values.
- Hard limit of 1024 filters makes display functionality extremely limited
In order to address this I am proposing moving the displaying of rules over
to the ETHTOOL_GRXCLSRLCNT/ETHTOOL_GRXCLSRULE/ETHTOOL_GRXCLSRULEALL
interfaces and will have a follow-on patch to allow this.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---
include/linux/ethtool.h | 7 -
include/linux/netdevice.h | 3
net/core/dev.c | 5 -
net/core/ethtool.c | 299 ---------------------------------------------
4 files changed, 1 insertions(+), 313 deletions(-)
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 3d1f8e0..2f2f27c 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -250,7 +250,6 @@ enum ethtool_stringset {
ETH_SS_TEST = 0,
ETH_SS_STATS,
ETH_SS_PRIV_FLAGS,
- ETH_SS_NTUPLE_FILTERS,
ETH_SS_FEATURES,
};
@@ -637,8 +636,6 @@ struct ethtool_rx_ntuple_flow_spec_container {
};
struct ethtool_rx_ntuple_list {
-#define ETHTOOL_MAX_NTUPLE_LIST_ENTRY 1024
-#define ETHTOOL_MAX_NTUPLE_STRING_PER_ENTRY 14
struct list_head list;
unsigned int count;
};
@@ -659,7 +656,6 @@ u32 ethtool_op_get_ufo(struct net_device *dev);
int ethtool_op_set_ufo(struct net_device *dev, u32 data);
u32 ethtool_op_get_flags(struct net_device *dev);
int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported);
-void ethtool_ntuple_flush(struct net_device *dev);
/**
* ðtool_ops - Alter and report network device settings
@@ -776,7 +772,6 @@ struct ethtool_ops {
int (*reset)(struct net_device *, u32 *);
int (*set_rx_ntuple)(struct net_device *,
struct ethtool_rx_ntuple *);
- int (*get_rx_ntuple)(struct net_device *, u32 stringset, void *);
int (*get_rxfh_indir)(struct net_device *,
struct ethtool_rxfh_indir *);
int (*set_rxfh_indir)(struct net_device *,
@@ -842,7 +837,7 @@ struct ethtool_ops {
#define ETHTOOL_FLASHDEV 0x00000033 /* Flash firmware to device */
#define ETHTOOL_RESET 0x00000034 /* Reset hardware */
#define ETHTOOL_SRXNTUPLE 0x00000035 /* Add an n-tuple filter to device */
-#define ETHTOOL_GRXNTUPLE 0x00000036 /* Get n-tuple filters from device */
+/* ETHTOOL_GRXNTUPLE 0x00000036 disabled due to multiple issues */
#define ETHTOOL_GSSET_INFO 0x00000037 /* Get string set info */
#define ETHTOOL_GRXFHINDIR 0x00000038 /* Get RX flow hash indir'n table */
#define ETHTOOL_SRXFHINDIR 0x00000039 /* Set RX flow hash indir'n table */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index ffe56c1..f20fabe 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1246,9 +1246,6 @@ struct net_device {
/* max exchange id for FCoE LRO by ddp */
unsigned int fcoe_ddp_xid;
#endif
- /* n-tuple filter list attached to this device */
- struct ethtool_rx_ntuple_list ethtool_ntuple_list;
-
/* phy device may attach itself for hardware timestamping */
struct phy_device *phydev;
diff --git a/net/core/dev.c b/net/core/dev.c
index 69a3c08..c788c98 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5886,8 +5886,6 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
dev->gso_max_size = GSO_MAX_SIZE;
- INIT_LIST_HEAD(&dev->ethtool_ntuple_list.list);
- dev->ethtool_ntuple_list.count = 0;
INIT_LIST_HEAD(&dev->napi_list);
INIT_LIST_HEAD(&dev->unreg_list);
INIT_LIST_HEAD(&dev->link_watch_list);
@@ -5951,9 +5949,6 @@ void free_netdev(struct net_device *dev)
/* Flush device addresses */
dev_addr_flush(dev);
- /* Clear ethtool n-tuple list */
- ethtool_ntuple_flush(dev);
-
list_for_each_entry_safe(p, n, &dev->napi_list, dev_list)
netif_napi_del(p);
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 4843674..3c5ba60 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -152,18 +152,6 @@ int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported)
}
EXPORT_SYMBOL(ethtool_op_set_flags);
-void ethtool_ntuple_flush(struct net_device *dev)
-{
- struct ethtool_rx_ntuple_flow_spec_container *fsc, *f;
-
- list_for_each_entry_safe(fsc, f, &dev->ethtool_ntuple_list.list, list) {
- list_del(&fsc->list);
- kfree(fsc);
- }
- dev->ethtool_ntuple_list.count = 0;
-}
-EXPORT_SYMBOL(ethtool_ntuple_flush);
-
/* Handlers for each ethtool command */
#define ETHTOOL_DEV_FEATURE_WORDS 1
@@ -825,34 +813,6 @@ out:
return ret;
}
-static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list,
- struct ethtool_rx_ntuple_flow_spec *spec,
- struct ethtool_rx_ntuple_flow_spec_container *fsc)
-{
-
- /* don't add filters forever */
- if (list->count >= ETHTOOL_MAX_NTUPLE_LIST_ENTRY) {
- /* free the container */
- kfree(fsc);
- return;
- }
-
- /* Copy the whole filter over */
- fsc->fs.flow_type = spec->flow_type;
- memcpy(&fsc->fs.h_u, &spec->h_u, sizeof(spec->h_u));
- memcpy(&fsc->fs.m_u, &spec->m_u, sizeof(spec->m_u));
-
- fsc->fs.vlan_tag = spec->vlan_tag;
- fsc->fs.vlan_tag_mask = spec->vlan_tag_mask;
- fsc->fs.data = spec->data;
- fsc->fs.data_mask = spec->data_mask;
- fsc->fs.action = spec->action;
-
- /* add to the list */
- list_add_tail_rcu(&fsc->list, &list->list);
- list->count++;
-}
-
/*
* ethtool does not (or did not) set masks for flow parameters that are
* not specified, so if both value and mask are 0 then this must be
@@ -904,268 +864,12 @@ static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev,
rx_ntuple_fix_masks(&cmd.fs);
- /*
- * Cache filter in dev struct for GET operation only if
- * the underlying driver doesn't have its own GET operation, and
- * only if the filter was added successfully. First make sure we
- * can allocate the filter, then continue if successful.
- */
- if (!ops->get_rx_ntuple) {
- fsc = kmalloc(sizeof(*fsc), GFP_ATOMIC);
- if (!fsc)
- return -ENOMEM;
- }
-
ret = ops->set_rx_ntuple(dev, &cmd);
if (ret) {
kfree(fsc);
return ret;
}
- if (!ops->get_rx_ntuple)
- __rx_ntuple_filter_add(&dev->ethtool_ntuple_list, &cmd.fs, fsc);
-
- return ret;
-}
-
-static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr)
-{
- struct ethtool_gstrings gstrings;
- const struct ethtool_ops *ops = dev->ethtool_ops;
- struct ethtool_rx_ntuple_flow_spec_container *fsc;
- u8 *data;
- char *p;
- int ret, i, num_strings = 0;
-
- if (!ops->get_sset_count)
- return -EOPNOTSUPP;
-
- if (copy_from_user(&gstrings, useraddr, sizeof(gstrings)))
- return -EFAULT;
-
- ret = ops->get_sset_count(dev, gstrings.string_set);
- if (ret < 0)
- return ret;
-
- gstrings.len = ret;
-
- data = kzalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
- if (!data)
- return -ENOMEM;
-
- if (ops->get_rx_ntuple) {
- /* driver-specific filter grab */
- ret = ops->get_rx_ntuple(dev, gstrings.string_set, data);
- goto copy;
- }
-
- /* default ethtool filter grab */
- i = 0;
- p = (char *)data;
- list_for_each_entry(fsc, &dev->ethtool_ntuple_list.list, list) {
- sprintf(p, "Filter %d:\n", i);
- p += ETH_GSTRING_LEN;
- num_strings++;
-
- switch (fsc->fs.flow_type) {
- case TCP_V4_FLOW:
- sprintf(p, "\tFlow Type: TCP\n");
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case UDP_V4_FLOW:
- sprintf(p, "\tFlow Type: UDP\n");
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case SCTP_V4_FLOW:
- sprintf(p, "\tFlow Type: SCTP\n");
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case AH_ESP_V4_FLOW:
- sprintf(p, "\tFlow Type: AH ESP\n");
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case ESP_V4_FLOW:
- sprintf(p, "\tFlow Type: ESP\n");
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case IP_USER_FLOW:
- sprintf(p, "\tFlow Type: Raw IP\n");
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case IPV4_FLOW:
- sprintf(p, "\tFlow Type: IPv4\n");
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- default:
- sprintf(p, "\tFlow Type: Unknown\n");
- p += ETH_GSTRING_LEN;
- num_strings++;
- goto unknown_filter;
- }
-
- /* now the rest of the filters */
- switch (fsc->fs.flow_type) {
- case TCP_V4_FLOW:
- case UDP_V4_FLOW:
- case SCTP_V4_FLOW:
- sprintf(p, "\tSrc IP addr: 0x%x\n",
- fsc->fs.h_u.tcp_ip4_spec.ip4src);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tSrc IP mask: 0x%x\n",
- fsc->fs.m_u.tcp_ip4_spec.ip4src);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest IP addr: 0x%x\n",
- fsc->fs.h_u.tcp_ip4_spec.ip4dst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest IP mask: 0x%x\n",
- fsc->fs.m_u.tcp_ip4_spec.ip4dst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tSrc Port: %d, mask: 0x%x\n",
- fsc->fs.h_u.tcp_ip4_spec.psrc,
- fsc->fs.m_u.tcp_ip4_spec.psrc);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest Port: %d, mask: 0x%x\n",
- fsc->fs.h_u.tcp_ip4_spec.pdst,
- fsc->fs.m_u.tcp_ip4_spec.pdst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tTOS: %d, mask: 0x%x\n",
- fsc->fs.h_u.tcp_ip4_spec.tos,
- fsc->fs.m_u.tcp_ip4_spec.tos);
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case AH_ESP_V4_FLOW:
- case ESP_V4_FLOW:
- sprintf(p, "\tSrc IP addr: 0x%x\n",
- fsc->fs.h_u.ah_ip4_spec.ip4src);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tSrc IP mask: 0x%x\n",
- fsc->fs.m_u.ah_ip4_spec.ip4src);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest IP addr: 0x%x\n",
- fsc->fs.h_u.ah_ip4_spec.ip4dst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest IP mask: 0x%x\n",
- fsc->fs.m_u.ah_ip4_spec.ip4dst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tSPI: %d, mask: 0x%x\n",
- fsc->fs.h_u.ah_ip4_spec.spi,
- fsc->fs.m_u.ah_ip4_spec.spi);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tTOS: %d, mask: 0x%x\n",
- fsc->fs.h_u.ah_ip4_spec.tos,
- fsc->fs.m_u.ah_ip4_spec.tos);
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case IP_USER_FLOW:
- sprintf(p, "\tSrc IP addr: 0x%x\n",
- fsc->fs.h_u.usr_ip4_spec.ip4src);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tSrc IP mask: 0x%x\n",
- fsc->fs.m_u.usr_ip4_spec.ip4src);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest IP addr: 0x%x\n",
- fsc->fs.h_u.usr_ip4_spec.ip4dst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest IP mask: 0x%x\n",
- fsc->fs.m_u.usr_ip4_spec.ip4dst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- case IPV4_FLOW:
- sprintf(p, "\tSrc IP addr: 0x%x\n",
- fsc->fs.h_u.usr_ip4_spec.ip4src);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tSrc IP mask: 0x%x\n",
- fsc->fs.m_u.usr_ip4_spec.ip4src);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest IP addr: 0x%x\n",
- fsc->fs.h_u.usr_ip4_spec.ip4dst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tDest IP mask: 0x%x\n",
- fsc->fs.m_u.usr_ip4_spec.ip4dst);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tL4 bytes: 0x%x, mask: 0x%x\n",
- fsc->fs.h_u.usr_ip4_spec.l4_4_bytes,
- fsc->fs.m_u.usr_ip4_spec.l4_4_bytes);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tTOS: %d, mask: 0x%x\n",
- fsc->fs.h_u.usr_ip4_spec.tos,
- fsc->fs.m_u.usr_ip4_spec.tos);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tIP Version: %d, mask: 0x%x\n",
- fsc->fs.h_u.usr_ip4_spec.ip_ver,
- fsc->fs.m_u.usr_ip4_spec.ip_ver);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tProtocol: %d, mask: 0x%x\n",
- fsc->fs.h_u.usr_ip4_spec.proto,
- fsc->fs.m_u.usr_ip4_spec.proto);
- p += ETH_GSTRING_LEN;
- num_strings++;
- break;
- }
- sprintf(p, "\tVLAN: %d, mask: 0x%x\n",
- fsc->fs.vlan_tag, fsc->fs.vlan_tag_mask);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tUser-defined: 0x%Lx\n", fsc->fs.data);
- p += ETH_GSTRING_LEN;
- num_strings++;
- sprintf(p, "\tUser-defined mask: 0x%Lx\n", fsc->fs.data_mask);
- p += ETH_GSTRING_LEN;
- num_strings++;
- if (fsc->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP)
- sprintf(p, "\tAction: Drop\n");
- else
- sprintf(p, "\tAction: Direct to queue %d\n",
- fsc->fs.action);
- p += ETH_GSTRING_LEN;
- num_strings++;
-unknown_filter:
- i++;
- }
-copy:
- /* indicate to userspace how many strings we actually have */
- gstrings.len = num_strings;
- ret = -EFAULT;
- if (copy_to_user(useraddr, &gstrings, sizeof(gstrings)))
- goto out;
- useraddr += sizeof(gstrings);
- if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN))
- goto out;
- ret = 0;
-
-out:
- kfree(data);
return ret;
}
@@ -1902,9 +1606,6 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
case ETHTOOL_SRXNTUPLE:
rc = ethtool_set_rx_ntuple(dev, useraddr);
break;
- case ETHTOOL_GRXNTUPLE:
- rc = ethtool_get_rx_ntuple(dev, useraddr);
- break;
case ETHTOOL_GSSET_INFO:
rc = ethtool_get_sset_info(dev, useraddr);
break;
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [net-next-2.6 PATCH 05/10] [RFC] ixgbe: add support for different Rx packet buffer sizes
2011-02-25 23:32 [net-next-2.6 PATCH 00/10] Workarounds and fixes for ntuple filters Alexander Duyck
` (3 preceding siblings ...)
2011-02-25 23:33 ` [net-next-2.6 PATCH 04/10] [RFC] ethtool: remove support for ETHTOOL_GRXNTUPLE Alexander Duyck
@ 2011-02-25 23:33 ` Alexander Duyck
2011-02-25 23:33 ` [net-next-2.6 PATCH 06/10] [RFC] ixgbe: update perfect filter framework to support retaining filters Alexander Duyck
` (4 subsequent siblings)
9 siblings, 0 replies; 24+ messages in thread
From: Alexander Duyck @ 2011-02-25 23:33 UTC (permalink / raw)
To: davem, jeffrey.t.kirsher, bhutchings; +Cc: netdev
This change adds support for hardware that can have different Rx packet
buffer sizes.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---
drivers/net/ixgbe/ixgbe_82598.c | 2 ++
drivers/net/ixgbe/ixgbe_82599.c | 2 ++
drivers/net/ixgbe/ixgbe_type.h | 1 +
drivers/net/ixgbe/ixgbe_x540.c | 2 ++
4 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c
index d0f1d9d..d2dc50c 100644
--- a/drivers/net/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ixgbe/ixgbe_82598.c
@@ -37,6 +37,7 @@
#define IXGBE_82598_RAR_ENTRIES 16
#define IXGBE_82598_MC_TBL_SIZE 128
#define IXGBE_82598_VFT_TBL_SIZE 128
+#define IXGBE_82598_RX_PB_SIZE 512
static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
@@ -123,6 +124,7 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw)
mac->mcft_size = IXGBE_82598_MC_TBL_SIZE;
mac->vft_size = IXGBE_82598_VFT_TBL_SIZE;
mac->num_rar_entries = IXGBE_82598_RAR_ENTRIES;
+ mac->rx_pb_size = IXGBE_82598_RX_PB_SIZE;
mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES;
mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES;
mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82598(hw);
diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c
index a21f581..c9bfa64 100644
--- a/drivers/net/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ixgbe/ixgbe_82599.c
@@ -38,6 +38,7 @@
#define IXGBE_82599_RAR_ENTRIES 128
#define IXGBE_82599_MC_TBL_SIZE 128
#define IXGBE_82599_VFT_TBL_SIZE 128
+#define IXGBE_82599_RX_PB_SIZE 512
static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
static void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
@@ -168,6 +169,7 @@ static s32 ixgbe_get_invariants_82599(struct ixgbe_hw *hw)
mac->vft_size = IXGBE_82599_VFT_TBL_SIZE;
mac->num_rar_entries = IXGBE_82599_RAR_ENTRIES;
mac->max_rx_queues = IXGBE_82599_MAX_RX_QUEUES;
+ mac->rx_pb_size = IXGBE_82599_RX_PB_SIZE;
mac->max_tx_queues = IXGBE_82599_MAX_TX_QUEUES;
mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw);
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index ab65d13..2f8ba73 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -2571,6 +2571,7 @@ struct ixgbe_mac_info {
u32 vft_size;
u32 num_rar_entries;
u32 rar_highwater;
+ u32 rx_pb_size;
u32 max_tx_queues;
u32 max_rx_queues;
u32 max_msix_vectors;
diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ixgbe/ixgbe_x540.c
index f2518b0..fa095f8 100644
--- a/drivers/net/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ixgbe/ixgbe_x540.c
@@ -38,6 +38,7 @@
#define IXGBE_X540_RAR_ENTRIES 128
#define IXGBE_X540_MC_TBL_SIZE 128
#define IXGBE_X540_VFT_TBL_SIZE 128
+#define IXGBE_X540_RX_PB_SIZE 384
static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw);
static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw);
@@ -62,6 +63,7 @@ static s32 ixgbe_get_invariants_X540(struct ixgbe_hw *hw)
mac->vft_size = IXGBE_X540_VFT_TBL_SIZE;
mac->num_rar_entries = IXGBE_X540_RAR_ENTRIES;
mac->max_rx_queues = IXGBE_X540_MAX_RX_QUEUES;
+ mac->rx_pb_size = IXGBE_X540_RX_PB_SIZE;
mac->max_tx_queues = IXGBE_X540_MAX_TX_QUEUES;
mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw);
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [net-next-2.6 PATCH 06/10] [RFC] ixgbe: update perfect filter framework to support retaining filters
2011-02-25 23:32 [net-next-2.6 PATCH 00/10] Workarounds and fixes for ntuple filters Alexander Duyck
` (4 preceding siblings ...)
2011-02-25 23:33 ` [net-next-2.6 PATCH 05/10] [RFC] ixgbe: add support for different Rx packet buffer sizes Alexander Duyck
@ 2011-02-25 23:33 ` Alexander Duyck
2011-02-25 23:33 ` [net-next-2.6 PATCH 07/10] [RFC] ixgbe: add basic support for settting and getting nfc controls Alexander Duyck
` (3 subsequent siblings)
9 siblings, 0 replies; 24+ messages in thread
From: Alexander Duyck @ 2011-02-25 23:33 UTC (permalink / raw)
To: davem, jeffrey.t.kirsher, bhutchings; +Cc: netdev
This change is meant to update the internal framework of ixgbe so that
perfect filters can be stored and tracked via software.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---
drivers/net/ixgbe/ixgbe.h | 18 +
drivers/net/ixgbe/ixgbe_82599.c | 659 +++++++++++++++++++++------------------
drivers/net/ixgbe/ixgbe_main.c | 2
drivers/net/ixgbe/ixgbe_type.h | 24 -
4 files changed, 376 insertions(+), 327 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index 12769b5..0cd75d6 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -526,16 +526,22 @@ extern void ixgbe_alloc_rx_buffers(struct ixgbe_ring *, u16);
extern void ixgbe_write_eitr(struct ixgbe_q_vector *);
extern int ethtool_ioctl(struct ifreq *ifr);
extern s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw);
-extern s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc);
-extern s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc);
+extern s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl);
+extern s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl);
extern s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
union ixgbe_atr_hash_dword input,
union ixgbe_atr_hash_dword common,
u8 queue);
-extern s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
- union ixgbe_atr_input *input,
- struct ixgbe_atr_input_masks *input_masks,
- u16 soft_id, u8 queue);
+extern s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input_mask);
+extern s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input,
+ u16 soft_id, u8 queue);
+extern s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input,
+ u16 soft_id);
+extern void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
+ union ixgbe_atr_input *mask);
extern void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
struct ixgbe_ring *ring);
extern void ixgbe_clear_rscctl(struct ixgbe_adapter *adapter,
diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c
index c9bfa64..e5fa29d 100644
--- a/drivers/net/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ixgbe/ixgbe_82599.c
@@ -413,14 +413,14 @@ static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
return status;
}
- /**
- * ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser
- * @hw: pointer to hardware structure
- *
- * The base drivers may require better control over SFP+ module
- * PHY states. This includes selectively shutting down the Tx
- * laser on the PHY, effectively halting physical link.
- **/
+/**
+ * ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser
+ * @hw: pointer to hardware structure
+ *
+ * The base drivers may require better control over SFP+ module
+ * PHY states. This includes selectively shutting down the Tx
+ * laser on the PHY, effectively halting physical link.
+ **/
static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
{
u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
@@ -1060,153 +1060,87 @@ s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
}
/**
- * ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters
+ * ixgbe_set_fdir_rxpba_82599 - Initialize Flow Director RX packet buffer
* @hw: pointer to hardware structure
* @pballoc: which mode to allocate filters with
**/
-s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc)
+static s32 ixgbe_set_fdir_rxpba_82599(struct ixgbe_hw *hw, const u32 pballoc)
{
- u32 fdirctrl = 0;
- u32 pbsize;
+ u32 fdir_pbsize = hw->mac.rx_pb_size << IXGBE_RXPBSIZE_SHIFT;
+ u32 current_rxpbsize = 0;
int i;
- /*
- * Before enabling Flow Director, the Rx Packet Buffer size
- * must be reduced. The new value is the current size minus
- * flow director memory usage size.
- */
- pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc));
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
- (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
-
- /*
- * The defaults in the HW for RX PB 1-7 are not zero and so should be
- * initialized to zero for non DCB mode otherwise actual total RX PB
- * would be bigger than programmed and filter space would run into
- * the PB 0 region.
- */
- for (i = 1; i < 8; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
-
- /* Send interrupt when 64 filters are left */
- fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
-
- /* Set the maximum length per hash bucket to 0xA filters */
- fdirctrl |= 0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT;
-
+ /* reserve space for Flow Director filters */
switch (pballoc) {
- case IXGBE_FDIR_PBALLOC_64K:
- /* 8k - 1 signature filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
+ case IXGBE_FDIR_PBALLOC_256K:
+ fdir_pbsize -= 256 << IXGBE_RXPBSIZE_SHIFT;
break;
case IXGBE_FDIR_PBALLOC_128K:
- /* 16k - 1 signature filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
+ fdir_pbsize -= 128 << IXGBE_RXPBSIZE_SHIFT;
break;
- case IXGBE_FDIR_PBALLOC_256K:
- /* 32k - 1 signature filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
+ case IXGBE_FDIR_PBALLOC_64K:
+ fdir_pbsize -= 64 << IXGBE_RXPBSIZE_SHIFT;
break;
+ case IXGBE_FDIR_PBALLOC_NONE:
default:
- /* bad value */
- return IXGBE_ERR_CONFIG;
- };
-
- /* Move the flexible bytes to use the ethertype - shift 6 words */
- fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
+ return IXGBE_ERR_PARAM;
+ }
+ /* determine current RX packet buffer size */
+ for (i = 0; i < 8; i++)
+ current_rxpbsize += IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
- /* Prime the keys for hashing */
- IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
- IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY);
+ /* if there is already room for the filters do nothing */
+ if (current_rxpbsize <= fdir_pbsize)
+ return 0;
- /*
- * Poll init-done after we write the register. Estimated times:
- * 10G: PBALLOC = 11b, timing is 60us
- * 1G: PBALLOC = 11b, timing is 600us
- * 100M: PBALLOC = 11b, timing is 6ms
- *
- * Multiple these timings by 4 if under full Rx load
- *
- * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for
- * 1 msec per poll time. If we're at line rate and drop to 100M, then
- * this might not finish in our poll time, but we can live with that
- * for now.
- */
- IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
- IXGBE_WRITE_FLUSH(hw);
- for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
- if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
- IXGBE_FDIRCTRL_INIT_DONE)
- break;
- msleep(1);
+ if (current_rxpbsize > hw->mac.rx_pb_size) {
+ /*
+ * if rxpbsize is greater than max then HW max the Rx buffer
+ * sizes are unconfigured or misconfigured since HW default is
+ * to give the full buffer to each traffic class resulting in
+ * the total size being buffer size 8x actual size
+ *
+ * This assumes no DCB since the RXPBSIZE registers appear to
+ * be unconfigured.
+ */
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), fdir_pbsize);
+ for (i = 1; i < 8; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
+ } else {
+ /*
+ * Since the Rx packet buffer appears to have already been
+ * configured we need to shrink each packet buffer by enough
+ * to make room for the filters. As such we take each rxpbsize
+ * value and multiply it by a fraction representing the size
+ * needed over the size we currently have.
+ *
+ * We need to reduce fdir_pbsize and current_rxpbsize to
+ * 1/1024 of their original values in order to avoid
+ * overflowing the u32 being used to store rxpbsize.
+ */
+ fdir_pbsize >>= IXGBE_RXPBSIZE_SHIFT;
+ current_rxpbsize >>= IXGBE_RXPBSIZE_SHIFT;
+ for (i = 0; i < 8; i++) {
+ u32 rxpbsize = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
+ rxpbsize *= fdir_pbsize;
+ rxpbsize /= current_rxpbsize;
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpbsize);
+ }
}
- if (i >= IXGBE_FDIR_INIT_DONE_POLL)
- hw_dbg(hw, "Flow Director Signature poll time exceeded!\n");
return 0;
}
/**
- * ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters
+ * ixgbe_fdir_enable_82599 - Initialize Flow Director control registers
* @hw: pointer to hardware structure
- * @pballoc: which mode to allocate filters with
+ * @fdirctrl: value to write to flow director control register
**/
-s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc)
+static void ixgbe_fdir_enable_82599(struct ixgbe_hw *hw, u32 fdirctrl)
{
- u32 fdirctrl = 0;
- u32 pbsize;
int i;
- /*
- * Before enabling Flow Director, the Rx Packet Buffer size
- * must be reduced. The new value is the current size minus
- * flow director memory usage size.
- */
- pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc));
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
- (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
-
- /*
- * The defaults in the HW for RX PB 1-7 are not zero and so should be
- * initialized to zero for non DCB mode otherwise actual total RX PB
- * would be bigger than programmed and filter space would run into
- * the PB 0 region.
- */
- for (i = 1; i < 8; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
-
- /* Send interrupt when 64 filters are left */
- fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
-
- /* Initialize the drop queue to Rx queue 127 */
- fdirctrl |= (127 << IXGBE_FDIRCTRL_DROP_Q_SHIFT);
-
- switch (pballoc) {
- case IXGBE_FDIR_PBALLOC_64K:
- /* 2k - 1 perfect filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
- break;
- case IXGBE_FDIR_PBALLOC_128K:
- /* 4k - 1 perfect filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
- break;
- case IXGBE_FDIR_PBALLOC_256K:
- /* 8k - 1 perfect filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
- break;
- default:
- /* bad value */
- return IXGBE_ERR_CONFIG;
- };
-
- /* Turn perfect match filtering on */
- fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH;
- fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS;
-
- /* Move the flexible bytes to use the ethertype - shift 6 words */
- fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
-
/* Prime the keys for hashing */
IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY);
@@ -1224,10 +1158,6 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc)
* this might not finish in our poll time, but we can live with that
* for now.
*/
-
- /* Set the maximum length per hash bucket to 0xA filters */
- fdirctrl |= (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT);
-
IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
IXGBE_WRITE_FLUSH(hw);
for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
@@ -1236,101 +1166,77 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc)
break;
msleep(1);
}
- if (i >= IXGBE_FDIR_INIT_DONE_POLL)
- hw_dbg(hw, "Flow Director Perfect poll time exceeded!\n");
- return 0;
+ if (i >= IXGBE_FDIR_INIT_DONE_POLL)
+ hw_dbg(hw, "Flow Director poll time exceeded!\n");
}
-
/**
- * ixgbe_atr_compute_hash_82599 - Compute the hashes for SW ATR
- * @stream: input bitstream to compute the hash on
- * @key: 32-bit hash key
+ * ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters
+ * @hw: pointer to hardware structure
+ * @fdirctrl: value to write to flow director control register, initially
+ * contains just the value of the Rx packet buffer allocation
**/
-static u32 ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *atr_input,
- u32 key)
+s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl)
{
- /*
- * The algorithm is as follows:
- * Hash[15:0] = Sum { S[n] x K[n+16] }, n = 0...350
- * where Sum {A[n]}, n = 0...n is bitwise XOR of A[0], A[1]...A[n]
- * and A[n] x B[n] is bitwise AND between same length strings
- *
- * K[n] is 16 bits, defined as:
- * for n modulo 32 >= 15, K[n] = K[n % 32 : (n % 32) - 15]
- * for n modulo 32 < 15, K[n] =
- * K[(n % 32:0) | (31:31 - (14 - (n % 32)))]
- *
- * S[n] is 16 bits, defined as:
- * for n >= 15, S[n] = S[n:n - 15]
- * for n < 15, S[n] = S[(n:0) | (350:350 - (14 - n))]
- *
- * To simplify for programming, the algorithm is implemented
- * in software this way:
- *
- * key[31:0], hi_hash_dword[31:0], lo_hash_dword[31:0], hash[15:0]
- *
- * for (i = 0; i < 352; i+=32)
- * hi_hash_dword[31:0] ^= Stream[(i+31):i];
- *
- * lo_hash_dword[15:0] ^= Stream[15:0];
- * lo_hash_dword[15:0] ^= hi_hash_dword[31:16];
- * lo_hash_dword[31:16] ^= hi_hash_dword[15:0];
- *
- * hi_hash_dword[31:0] ^= Stream[351:320];
- *
- * if(key[0])
- * hash[15:0] ^= Stream[15:0];
- *
- * for (i = 0; i < 16; i++) {
- * if (key[i])
- * hash[15:0] ^= lo_hash_dword[(i+15):i];
- * if (key[i + 16])
- * hash[15:0] ^= hi_hash_dword[(i+15):i];
- * }
- *
- */
- __be32 common_hash_dword = 0;
- u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
- u32 hash_result = 0;
- u8 i;
+ s32 err;
- /* record the flow_vm_vlan bits as they are a key part to the hash */
- flow_vm_vlan = ntohl(atr_input->dword_stream[0]);
+ /* Before enabling Flow Director, verify the Rx Packet Buffer size */
+ err = ixgbe_set_fdir_rxpba_82599(hw, fdirctrl);
+ if (err)
+ return err;
- /* generate common hash dword */
- for (i = 10; i; i -= 2)
- common_hash_dword ^= atr_input->dword_stream[i] ^
- atr_input->dword_stream[i - 1];
+ /*
+ * Continue setup of fdirctrl register bits:
+ * Move the flexible bytes to use the ethertype - shift 6 words
+ * Set the maximum length per hash bucket to 0xA filters
+ * Send interrupt when 64 filters are left
+ */
+ fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
+ (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
+ (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
- hi_hash_dword = ntohl(common_hash_dword);
+ /* write hashes and fdirctrl register, poll for completion */
+ ixgbe_fdir_enable_82599(hw, fdirctrl);
- /* low dword is word swapped version of common */
- lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
+ return 0;
+}
- /* apply flow ID/VM pool/VLAN ID bits to hash words */
- hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
+/**
+ * ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters
+ * @hw: pointer to hardware structure
+ * @fdirctrl: value to write to flow director control register, initially
+ * contains just the value of the Rx packet buffer allocation
+ **/
+s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl)
+{
+ s32 err;
- /* Process bits 0 and 16 */
- if (key & 0x0001) hash_result ^= lo_hash_dword;
- if (key & 0x00010000) hash_result ^= hi_hash_dword;
+ /* Before enabling Flow Director, verify the Rx Packet Buffer size */
+ err = ixgbe_set_fdir_rxpba_82599(hw, fdirctrl);
+ if (err)
+ return err;
/*
- * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
- * delay this because bit 0 of the stream should not be processed
- * so we do not add the vlan until after bit 0 was processed
+ * Continue setup of fdirctrl register bits:
+ * Turn perfect match filtering on
+ * Report hash in RSS field of Rx wb descriptor
+ * Initialize the drop queue
+ * Move the flexible bytes to use the ethertype - shift 6 words
+ * Set the maximum length per hash bucket to 0xA filters
+ * Send interrupt when 64 (0x4 * 16) filters are left
*/
- lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
-
+ fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH |
+ IXGBE_FDIRCTRL_REPORT_STATUS |
+ (IXGBE_FDIR_DROP_QUEUE << IXGBE_FDIRCTRL_DROP_Q_SHIFT) |
+ (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
+ (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
+ (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
- /* process the remaining 30 bits in the key 2 bits at a time */
- for (i = 15; i; i-- ) {
- if (key & (0x0001 << i)) hash_result ^= lo_hash_dword >> i;
- if (key & (0x00010000 << i)) hash_result ^= hi_hash_dword >> i;
- }
+ /* write hashes and fdirctrl register, poll for completion */
+ ixgbe_fdir_enable_82599(hw, fdirctrl);
- return hash_result & IXGBE_ATR_HASH_MASK;
+ return 0;
}
/*
@@ -1467,7 +1373,6 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
*/
fdirhashcmd = (u64)fdircmd << 32;
fdirhashcmd |= ixgbe_atr_compute_sig_hash_82599(input, common);
-
IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd);
hw_dbg(hw, "Tx Queue=%x hash=%x\n", queue, (u32)fdirhashcmd);
@@ -1475,6 +1380,101 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
return 0;
}
+#define IXGBE_COMPUTE_BKT_HASH_ITERATION(_n) \
+do { \
+ u32 n = (_n); \
+ if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \
+ bucket_hash ^= lo_hash_dword >> n; \
+ if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \
+ bucket_hash ^= hi_hash_dword >> n; \
+} while (0);
+
+/**
+ * ixgbe_atr_compute_perfect_hash_82599 - Compute the perfect filter hash
+ * @atr_input: input bitstream to compute the hash on
+ * @input_mask: mask for the input bitstream
+ *
+ * This function serves two main purposes. First it applys the input_mask
+ * to the atr_input resulting in a cleaned up atr_input data stream.
+ * Secondly it computes the hash and stores it in the bkt_hash field at
+ * the end of the input byte stream. This way it will be available for
+ * future use without needing to recompute the hash.
+ **/
+void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
+ union ixgbe_atr_input *input_mask)
+{
+
+ u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
+ u32 bucket_hash = 0;
+
+ /* Apply masks to input data */
+ input->dword_stream[0] &= input_mask->dword_stream[0];
+ input->dword_stream[1] &= input_mask->dword_stream[1];
+ input->dword_stream[2] &= input_mask->dword_stream[2];
+ input->dword_stream[3] &= input_mask->dword_stream[3];
+ input->dword_stream[4] &= input_mask->dword_stream[4];
+ input->dword_stream[5] &= input_mask->dword_stream[5];
+ input->dword_stream[6] &= input_mask->dword_stream[6];
+ input->dword_stream[7] &= input_mask->dword_stream[7];
+ input->dword_stream[8] &= input_mask->dword_stream[8];
+ input->dword_stream[9] &= input_mask->dword_stream[9];
+ input->dword_stream[10] &= input_mask->dword_stream[10];
+
+ /* record the flow_vm_vlan bits as they are a key part to the hash */
+ flow_vm_vlan = ntohl(input->dword_stream[0]);
+
+ /* generate common hash dword */
+ hi_hash_dword = ntohl(input->dword_stream[1] ^
+ input->dword_stream[2] ^
+ input->dword_stream[3] ^
+ input->dword_stream[4] ^
+ input->dword_stream[5] ^
+ input->dword_stream[6] ^
+ input->dword_stream[7] ^
+ input->dword_stream[8] ^
+ input->dword_stream[9] ^
+ input->dword_stream[10]);
+
+ /* low dword is word swapped version of common */
+ lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
+
+ /* apply flow ID/VM pool/VLAN ID bits to hash words */
+ hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
+
+ /* Process bits 0 and 16 */
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(0);
+
+ /*
+ * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
+ * delay this because bit 0 of the stream should not be processed
+ * so we do not add the vlan until after bit 0 was processed
+ */
+ lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
+
+ /* Process remaining 30 bit of the key */
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(1);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(2);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(3);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(4);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(5);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(6);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(7);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(8);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(9);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(10);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(11);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(12);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(13);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(14);
+ IXGBE_COMPUTE_BKT_HASH_ITERATION(15);
+
+ /*
+ * Limit hash to 13 bits since max bucket count is 8K.
+ * Store result at the end of the input stream.
+ */
+ input->formatted.bkt_hash = bucket_hash & 0x1FFF;
+}
+
/**
* ixgbe_get_fdirtcpm_82599 - generate a tcp port from atr_input_masks
* @input_mask: mask to be bit swapped
@@ -1484,11 +1484,11 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
* generate a correctly swapped value we need to bit swap the mask and that
* is what is accomplished by this function.
**/
-static u32 ixgbe_get_fdirtcpm_82599(struct ixgbe_atr_input_masks *input_masks)
+static u32 ixgbe_get_fdirtcpm_82599(union ixgbe_atr_input *input_mask)
{
- u32 mask = ntohs(input_masks->dst_port_mask);
+ u32 mask = ntohs(input_mask->formatted.dst_port);
mask <<= IXGBE_FDIRTCPM_DPORTM_SHIFT;
- mask |= ntohs(input_masks->src_port_mask);
+ mask |= ntohs(input_mask->formatted.src_port);
mask = ((mask & 0x55555555) << 1) | ((mask & 0xAAAAAAAA) >> 1);
mask = ((mask & 0x33333333) << 2) | ((mask & 0xCCCCCCCC) >> 2);
mask = ((mask & 0x0F0F0F0F) << 4) | ((mask & 0xF0F0F0F0) >> 4);
@@ -1510,52 +1510,14 @@ static u32 ixgbe_get_fdirtcpm_82599(struct ixgbe_atr_input_masks *input_masks)
IXGBE_WRITE_REG((a), (reg), IXGBE_STORE_AS_BE32(ntohl(value)))
#define IXGBE_STORE_AS_BE16(_value) \
- (((u16)(_value) >> 8) | ((u16)(_value) << 8))
+ ntohs(((u16)(_value) >> 8) | ((u16)(_value) << 8))
-/**
- * ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter
- * @hw: pointer to hardware structure
- * @input: input bitstream
- * @input_masks: bitwise masks for relevant fields
- * @soft_id: software index into the silicon hash tables for filter storage
- * @queue: queue index to direct traffic to
- *
- * Note that the caller to this function must lock before calling, since the
- * hardware writes must be protected from one another.
- **/
-s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
- union ixgbe_atr_input *input,
- struct ixgbe_atr_input_masks *input_masks,
- u16 soft_id, u8 queue)
+s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input_mask)
{
- u32 fdirhash;
- u32 fdircmd;
- u32 fdirport, fdirtcpm;
- u32 fdirvlan;
- /* start with VLAN, flex bytes, VM pool, and IPv6 destination masked */
- u32 fdirm = IXGBE_FDIRM_VLANID | IXGBE_FDIRM_VLANP | IXGBE_FDIRM_FLEX |
- IXGBE_FDIRM_POOL | IXGBE_FDIRM_DIPv6;
-
- /*
- * Check flow_type formatting, and bail out before we touch the hardware
- * if there's a configuration issue
- */
- switch (input->formatted.flow_type) {
- case IXGBE_ATR_FLOW_TYPE_IPV4:
- /* use the L4 protocol mask for raw IPv4/IPv6 traffic */
- fdirm |= IXGBE_FDIRM_L4P;
- case IXGBE_ATR_FLOW_TYPE_SCTPV4:
- if (input_masks->dst_port_mask || input_masks->src_port_mask) {
- hw_dbg(hw, " Error on src/dst port mask\n");
- return IXGBE_ERR_CONFIG;
- }
- case IXGBE_ATR_FLOW_TYPE_TCPV4:
- case IXGBE_ATR_FLOW_TYPE_UDPV4:
- break;
- default:
- hw_dbg(hw, " Error on flow type input\n");
- return IXGBE_ERR_CONFIG;
- }
+ /* mask IPv6 since it is currently not supported */
+ u32 fdirm = IXGBE_FDIRM_DIPv6;
+ u32 fdirtcpm;
/*
* Program the relevant mask registers. If src/dst_port or src/dst_addr
@@ -1567,41 +1529,71 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
* point in time.
*/
- /* Program FDIRM */
- switch (ntohs(input_masks->vlan_id_mask) & 0xEFFF) {
- case 0xEFFF:
- /* Unmask VLAN ID - bit 0 and fall through to unmask prio */
- fdirm &= ~IXGBE_FDIRM_VLANID;
- case 0xE000:
- /* Unmask VLAN prio - bit 1 */
- fdirm &= ~IXGBE_FDIRM_VLANP;
+ /* verify bucket hash is cleared on hash generation */
+ if (input_mask->formatted.bkt_hash)
+ hw_dbg(hw, " bucket hash should always be 0 in mask\n");
+
+ /* Program FDIRM and verify partial masks */
+ switch (input_mask->formatted.vm_pool & 0x7F) {
+ case 0x0:
+ fdirm |= IXGBE_FDIRM_POOL;
+ case 0x7F:
break;
- case 0x0FFF:
- /* Unmask VLAN ID - bit 0 */
- fdirm &= ~IXGBE_FDIRM_VLANID;
+ default:
+ hw_dbg(hw, " Error on vm pool mask\n");
+ return IXGBE_ERR_CONFIG;
+ }
+
+ switch (input_mask->formatted.flow_type & IXGBE_ATR_L4TYPE_MASK) {
+ case 0x0:
+ fdirm |= IXGBE_FDIRM_L4P;
+ if (input_mask->formatted.dst_port ||
+ input_mask->formatted.src_port) {
+ hw_dbg(hw, " Error on src/dst port mask\n");
+ return IXGBE_ERR_CONFIG;
+ }
+ case IXGBE_ATR_L4TYPE_MASK:
break;
+ default:
+ hw_dbg(hw, " Error on flow type mask\n");
+ return IXGBE_ERR_CONFIG;
+ }
+
+ switch (ntohs(input_mask->formatted.vlan_id) & 0xEFFF) {
case 0x0000:
- /* do nothing, vlans already masked */
+ /* mask VLAN ID, fall through to mask VLAN priority */
+ fdirm |= IXGBE_FDIRM_VLANID;
+ case 0x0FFF:
+ /* mask VLAN priority */
+ fdirm |= IXGBE_FDIRM_VLANP;
+ break;
+ case 0xE000:
+ /* mask VLAN ID only, fall through */
+ fdirm |= IXGBE_FDIRM_VLANID;
+ case 0xEFFF:
+ /* no VLAN fields masked */
break;
default:
hw_dbg(hw, " Error on VLAN mask\n");
return IXGBE_ERR_CONFIG;
}
- if (input_masks->flex_mask & 0xFFFF) {
- if ((input_masks->flex_mask & 0xFFFF) != 0xFFFF) {
- hw_dbg(hw, " Error on flexible byte mask\n");
- return IXGBE_ERR_CONFIG;
- }
- /* Unmask Flex Bytes - bit 4 */
- fdirm &= ~IXGBE_FDIRM_FLEX;
+ switch (input_mask->formatted.flex_bytes & 0xFFFF) {
+ case 0x0000:
+ /* Mask Flex Bytes, fall through */
+ fdirm |= IXGBE_FDIRM_FLEX;
+ case 0xFFFF:
+ break;
+ default:
+ hw_dbg(hw, " Error on flexible byte mask\n");
+ return IXGBE_ERR_CONFIG;
}
/* Now mask VM pool and destination IPv6 - bits 5 and 2 */
IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
/* store the TCP/UDP port masks, bit reversed from port layout */
- fdirtcpm = ixgbe_get_fdirtcpm_82599(input_masks);
+ fdirtcpm = ixgbe_get_fdirtcpm_82599(input_mask);
/* write both the same so that UDP and TCP use the same mask */
IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm);
@@ -1609,24 +1601,32 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
/* store source and destination IP masks (big-enian) */
IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M,
- ~input_masks->src_ip_mask[0]);
+ ~input_mask->formatted.src_ip[0]);
IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M,
- ~input_masks->dst_ip_mask[0]);
+ ~input_mask->formatted.dst_ip[0]);
- /* Apply masks to input data */
- input->formatted.vlan_id &= input_masks->vlan_id_mask;
- input->formatted.flex_bytes &= input_masks->flex_mask;
- input->formatted.src_port &= input_masks->src_port_mask;
- input->formatted.dst_port &= input_masks->dst_port_mask;
- input->formatted.src_ip[0] &= input_masks->src_ip_mask[0];
- input->formatted.dst_ip[0] &= input_masks->dst_ip_mask[0];
+ return 0;
+}
- /* record vlan (little-endian) and flex_bytes(big-endian) */
- fdirvlan =
- IXGBE_STORE_AS_BE16(ntohs(input->formatted.flex_bytes));
- fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
- fdirvlan |= ntohs(input->formatted.vlan_id);
- IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);
+s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input,
+ u16 soft_id, u8 queue)
+{
+ u32 fdirport, fdirvlan, fdirhash, fdircmd;
+
+ /* currently IPv6 is not supported, must be programmed with 0 */
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0),
+ input->formatted.src_ip[0]);
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(1),
+ input->formatted.src_ip[1]);
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(2),
+ input->formatted.src_ip[2]);
+
+ /* record the source address (big-endian) */
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]);
+
+ /* record the first 32 bits of the destination address (big-endian) */
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]);
/* record source and destination port (little-endian)*/
fdirport = ntohs(input->formatted.dst_port);
@@ -1634,29 +1634,80 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
fdirport |= ntohs(input->formatted.src_port);
IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport);
- /* record the first 32 bits of the destination address (big-endian) */
- IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]);
+ /* record vlan (little-endian) and flex_bytes(big-endian) */
+ fdirvlan = IXGBE_STORE_AS_BE16(input->formatted.flex_bytes);
+ fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
+ fdirvlan |= ntohs(input->formatted.vlan_id);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);
- /* record the source address (big-endian) */
- IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]);
+ /* configure FDIRHASH register */
+ fdirhash = input->formatted.bkt_hash;
+ fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
+
+ /*
+ * flush all previous writes to make certain registers are
+ * programmed prior to issuing the command
+ */
+ IXGBE_WRITE_FLUSH(hw);
/* configure FDIRCMD register */
fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
+ if (queue == IXGBE_FDIR_DROP_QUEUE)
+ fdircmd |= IXGBE_FDIRCMD_DROP;
fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
+ fdircmd |= (u32)input->formatted.vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT;
- /* we only want the bucket hash so drop the upper 16 bits */
- fdirhash = ixgbe_atr_compute_hash_82599(input,
- IXGBE_ATR_BUCKET_HASH_KEY);
- fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
-
- IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
return 0;
}
+s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input,
+ u16 soft_id)
+{
+ u32 fdirhash;
+ u32 fdircmd = 0;
+ u32 retry_count;
+ s32 err = 0;
+
+ /* configure FDIRHASH register */
+ fdirhash = input->formatted.bkt_hash;
+ fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
+
+ /* flush hash to HW */
+ IXGBE_WRITE_FLUSH(hw);
+
+ /* Query if filter is present */
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_QUERY_REM_FILT);
+
+ for (retry_count = 10; retry_count; retry_count--) {
+ /* allow 10us for query to process */
+ udelay(10);
+ /* verify query completed successfully */
+ fdircmd = IXGBE_READ_REG(hw, IXGBE_FDIRCMD);
+ if (!(fdircmd & IXGBE_FDIRCMD_CMD_MASK))
+ break;
+ }
+
+ if (!retry_count)
+ err = IXGBE_ERR_FDIR_REINIT_FAILED;
+
+ /* if filter exists in hardware then remove it */
+ if (fdircmd & IXGBE_FDIRCMD_FILTER_VALID) {
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
+ IXGBE_WRITE_FLUSH(hw);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
+ IXGBE_FDIRCMD_CMD_REMOVE_FLOW);
+ }
+
+ return err;
+}
+
/**
* ixgbe_read_analog_reg8_82599 - Reads 8 bit Omer analog register
* @hw: pointer to hardware structure
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 929f059..6b6f602 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -5137,7 +5137,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
adapter->atr_sample_rate = 20;
adapter->ring_feature[RING_F_FDIR].indices =
IXGBE_MAX_FDIR_INDICES;
- adapter->fdir_pballoc = 0;
+ adapter->fdir_pballoc = IXGBE_FDIR_PBALLOC_64K;
#ifdef IXGBE_FCOE
adapter->flags |= IXGBE_FLAG_FCOE_CAPABLE;
adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index 2f8ba73..efcf65e 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -1922,9 +1922,10 @@
#endif
enum ixgbe_fdir_pballoc_type {
- IXGBE_FDIR_PBALLOC_64K = 0,
- IXGBE_FDIR_PBALLOC_128K,
- IXGBE_FDIR_PBALLOC_256K,
+ IXGBE_FDIR_PBALLOC_NONE = 0,
+ IXGBE_FDIR_PBALLOC_64K = 1,
+ IXGBE_FDIR_PBALLOC_128K = 2,
+ IXGBE_FDIR_PBALLOC_256K = 3,
};
#define IXGBE_FDIR_PBALLOC_SIZE_SHIFT 16
@@ -1978,7 +1979,7 @@ enum ixgbe_fdir_pballoc_type {
#define IXGBE_FDIRCMD_CMD_ADD_FLOW 0x00000001
#define IXGBE_FDIRCMD_CMD_REMOVE_FLOW 0x00000002
#define IXGBE_FDIRCMD_CMD_QUERY_REM_FILT 0x00000003
-#define IXGBE_FDIRCMD_CMD_QUERY_REM_HASH 0x00000007
+#define IXGBE_FDIRCMD_FILTER_VALID 0x00000004
#define IXGBE_FDIRCMD_FILTER_UPDATE 0x00000008
#define IXGBE_FDIRCMD_IPv6DMATCH 0x00000010
#define IXGBE_FDIRCMD_L4TYPE_UDP 0x00000020
@@ -1997,6 +1998,7 @@ enum ixgbe_fdir_pballoc_type {
#define IXGBE_FDIR_INIT_DONE_POLL 10
#define IXGBE_FDIRCMD_CMD_POLL 10
+#define IXGBE_FDIR_DROP_QUEUE 127
/* Transmit Descriptor - Advanced */
union ixgbe_adv_tx_desc {
struct {
@@ -2183,7 +2185,7 @@ union ixgbe_atr_input {
* src_port - 2 bytes
* dst_port - 2 bytes
* flex_bytes - 2 bytes
- * rsvd0 - 2 bytes - space reserved must be 0.
+ * bkt_hash - 2 bytes
*/
struct {
u8 vm_pool;
@@ -2194,7 +2196,7 @@ union ixgbe_atr_input {
__be16 src_port;
__be16 dst_port;
__be16 flex_bytes;
- __be16 rsvd0;
+ __be16 bkt_hash;
} formatted;
__be32 dword_stream[11];
};
@@ -2215,16 +2217,6 @@ union ixgbe_atr_hash_dword {
__be32 dword;
};
-struct ixgbe_atr_input_masks {
- __be16 rsvd0;
- __be16 vlan_id_mask;
- __be32 dst_ip_mask[4];
- __be32 src_ip_mask[4];
- __be16 src_port_mask;
- __be16 dst_port_mask;
- __be16 flex_mask;
-};
-
enum ixgbe_eeprom_type {
ixgbe_eeprom_uninitialized = 0,
ixgbe_eeprom_spi,
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [net-next-2.6 PATCH 07/10] [RFC] ixgbe: add basic support for settting and getting nfc controls
2011-02-25 23:32 [net-next-2.6 PATCH 00/10] Workarounds and fixes for ntuple filters Alexander Duyck
` (5 preceding siblings ...)
2011-02-25 23:33 ` [net-next-2.6 PATCH 06/10] [RFC] ixgbe: update perfect filter framework to support retaining filters Alexander Duyck
@ 2011-02-25 23:33 ` Alexander Duyck
2011-02-25 23:33 ` [net-next-2.6 PATCH 08/10] [RFC] ixgbe: add support for displaying ntuple filters via the nfc interface Alexander Duyck
` (2 subsequent siblings)
9 siblings, 0 replies; 24+ messages in thread
From: Alexander Duyck @ 2011-02-25 23:33 UTC (permalink / raw)
To: davem, jeffrey.t.kirsher, bhutchings; +Cc: netdev
This change adds basic suppport for the obtaining of RSS ring counts and
setting of RSS hash options.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---
drivers/net/ixgbe/ixgbe_ethtool.c | 60 +++++++++++++++++++++++++++++++++++++
1 files changed, 60 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 1b40c02..6c17e45 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -2299,6 +2299,65 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
return 0;
}
+static int ixgbe_get_rss_hash_opts(struct ixgbe_adapter *adapter,
+ struct ethtool_rxnfc *cmd)
+{
+ cmd->data = 0;
+
+ /* if RSS is disabled then report no hashing */
+ if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED))
+ return 0;
+
+ /* Report default options for RSS on ixgbe */
+ switch (cmd->flow_type) {
+ case TCP_V4_FLOW:
+ cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ case UDP_V4_FLOW:
+ case SCTP_V4_FLOW:
+ case AH_ESP_V4_FLOW:
+ case AH_V4_FLOW:
+ case ESP_V4_FLOW:
+ case IPV4_FLOW:
+ cmd->data |= RXH_IP_SRC | RXH_IP_DST;
+ break;
+ case TCP_V6_FLOW:
+ cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ case UDP_V6_FLOW:
+ case SCTP_V6_FLOW:
+ case AH_ESP_V6_FLOW:
+ case AH_V6_FLOW:
+ case ESP_V6_FLOW:
+ case IPV6_FLOW:
+ cmd->data |= RXH_IP_SRC | RXH_IP_DST;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+ void *rule_locs)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ int ret = -EOPNOTSUPP;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_GRXFH:
+ ret = ixgbe_get_rss_hash_opts(adapter, cmd);
+ break;
+ case ETHTOOL_GRXRINGS:
+ cmd->data = adapter->num_rx_queues;
+ ret = 0;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
static const struct ethtool_ops ixgbe_ethtool_ops = {
.get_settings = ixgbe_get_settings,
.set_settings = ixgbe_set_settings,
@@ -2334,6 +2393,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
.set_coalesce = ixgbe_set_coalesce,
.get_flags = ethtool_op_get_flags,
.set_flags = ixgbe_set_flags,
+ .get_rxnfc = ixgbe_get_rxnfc,
};
void ixgbe_set_ethtool_ops(struct net_device *netdev)
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [net-next-2.6 PATCH 08/10] [RFC] ixgbe: add support for displaying ntuple filters via the nfc interface
2011-02-25 23:32 [net-next-2.6 PATCH 00/10] Workarounds and fixes for ntuple filters Alexander Duyck
` (6 preceding siblings ...)
2011-02-25 23:33 ` [net-next-2.6 PATCH 07/10] [RFC] ixgbe: add basic support for settting and getting nfc controls Alexander Duyck
@ 2011-02-25 23:33 ` Alexander Duyck
2011-02-25 23:33 ` [net-next-2.6 PATCH 09/10] [RFC] ixgbe: add support for nfc addition and removal of filters Alexander Duyck
2011-02-25 23:33 ` [net-next-2.6 PATCH 10/10] [RFC] ixgbe: Add support for using the same fields as ntuple in nfc Alexander Duyck
9 siblings, 0 replies; 24+ messages in thread
From: Alexander Duyck @ 2011-02-25 23:33 UTC (permalink / raw)
To: davem, jeffrey.t.kirsher, bhutchings; +Cc: netdev
This code adds support for displaying the filters that were added via the
nfc interface. This is primarily to test the interface for now, but I am
also looking into the feasability of moving all of the ntuple filter code
in ixgbe over to the nfc interface since it seems to be better implemented.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---
drivers/net/ixgbe/ixgbe.h | 11 ++++
drivers/net/ixgbe/ixgbe_ethtool.c | 95 +++++++++++++++++++++++++++++++++++++
2 files changed, 106 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index 0cd75d6..903c828 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -466,6 +466,17 @@ struct ixgbe_adapter {
DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS);
unsigned int num_vfs;
struct vf_data_storage *vfinfo;
+
+ struct hlist_head fdir_filter_list;
+ union ixgbe_atr_input fdir_mask;
+ int fdir_filter_count;
+};
+
+struct ixgbe_fdir_filter {
+ struct hlist_node fdir_node;
+ union ixgbe_atr_input filter;
+ u16 sw_idx;
+ u16 action;
};
enum ixbge_state_t {
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 6c17e45..145e018 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -2337,6 +2337,89 @@ static int ixgbe_get_rss_hash_opts(struct ixgbe_adapter *adapter,
return 0;
}
+static int ixgbe_get_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
+ struct ethtool_rxnfc *cmd)
+{
+ union ixgbe_atr_input *mask = &adapter->fdir_mask;
+ struct ethtool_rx_flow_spec *fsp =
+ (struct ethtool_rx_flow_spec *)&cmd->fs;
+ struct hlist_node *node, *node2;
+ struct ixgbe_fdir_filter *rule = NULL;
+
+ /* report total rule count */
+ cmd->data = (1024 << adapter->fdir_pballoc) - 2;
+
+ hlist_for_each_entry_safe(rule, node, node2,
+ &adapter->fdir_filter_list, fdir_node) {
+ if (fsp->location <= rule->sw_idx)
+ break;
+ }
+
+ if (!rule || fsp->location != rule->sw_idx)
+ return -EINVAL;
+
+ /* fill out the flow spec entry */
+
+ /* set flow type field */
+ switch (rule->filter.formatted.flow_type) {
+ case IXGBE_ATR_FLOW_TYPE_TCPV4:
+ fsp->flow_type = TCP_V4_FLOW;
+ break;
+ case IXGBE_ATR_FLOW_TYPE_UDPV4:
+ fsp->flow_type = UDP_V4_FLOW;
+ break;
+ case IXGBE_ATR_FLOW_TYPE_SCTPV4:
+ fsp->flow_type = SCTP_V4_FLOW;
+ break;
+ case IXGBE_ATR_FLOW_TYPE_IPV4:
+ fsp->flow_type = IP_USER_FLOW;
+ fsp->h_u.usr_ip4_spec.proto = 0;
+ fsp->m_u.usr_ip4_spec.proto = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ fsp->h_u.tcp_ip4_spec.psrc = rule->filter.formatted.src_port;
+ fsp->m_u.tcp_ip4_spec.psrc = mask->formatted.src_port;
+ fsp->h_u.tcp_ip4_spec.pdst = rule->filter.formatted.dst_port;
+ fsp->m_u.tcp_ip4_spec.pdst = mask->formatted.dst_port;
+ fsp->h_u.tcp_ip4_spec.ip4src = rule->filter.formatted.src_ip[0];
+ fsp->m_u.tcp_ip4_spec.ip4src = mask->formatted.src_ip[0];
+ fsp->h_u.tcp_ip4_spec.ip4dst = rule->filter.formatted.dst_ip[0];
+ fsp->m_u.tcp_ip4_spec.ip4dst = mask->formatted.dst_ip[0];
+
+ /* record action */
+ if (rule->action == IXGBE_FDIR_DROP_QUEUE)
+ fsp->ring_cookie = RX_CLS_FLOW_DISC;
+ else
+ fsp->ring_cookie = rule->action;
+
+ return 0;
+}
+
+static int ixgbe_get_ethtool_fdir_all(struct ixgbe_adapter *adapter,
+ struct ethtool_rxnfc *cmd,
+ u32 *rule_locs)
+{
+ struct hlist_node *node, *node2;
+ struct ixgbe_fdir_filter *rule;
+ int cnt = 0;
+
+ /* report total rule count */
+ cmd->data = (1024 << adapter->fdir_pballoc) - 2;
+
+ hlist_for_each_entry_safe(rule, node, node2,
+ &adapter->fdir_filter_list, fdir_node) {
+ if (cnt == cmd->rule_cnt)
+ return -EMSGSIZE;
+ rule_locs[cnt] = rule->sw_idx;
+ cnt++;
+ }
+
+ return 0;
+}
+
static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
void *rule_locs)
{
@@ -2351,6 +2434,18 @@ static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
cmd->data = adapter->num_rx_queues;
ret = 0;
break;
+ case ETHTOOL_GRXCLSRLCNT:
+ cmd->rule_cnt = adapter->fdir_filter_count;
+ ret = 0;
+ break;
+ case ETHTOOL_GRXCLSRULE:
+ ret = ixgbe_get_ethtool_fdir_entry(adapter, cmd);
+ break;
+ case ETHTOOL_GRXCLSRLALL:
+ ret = ixgbe_get_ethtool_fdir_all(adapter, cmd,
+ (u32 *)rule_locs);
+ break;
+
default:
break;
}
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [net-next-2.6 PATCH 09/10] [RFC] ixgbe: add support for nfc addition and removal of filters
2011-02-25 23:32 [net-next-2.6 PATCH 00/10] Workarounds and fixes for ntuple filters Alexander Duyck
` (7 preceding siblings ...)
2011-02-25 23:33 ` [net-next-2.6 PATCH 08/10] [RFC] ixgbe: add support for displaying ntuple filters via the nfc interface Alexander Duyck
@ 2011-02-25 23:33 ` Alexander Duyck
2011-02-25 23:33 ` [net-next-2.6 PATCH 10/10] [RFC] ixgbe: Add support for using the same fields as ntuple in nfc Alexander Duyck
9 siblings, 0 replies; 24+ messages in thread
From: Alexander Duyck @ 2011-02-25 23:33 UTC (permalink / raw)
To: davem, jeffrey.t.kirsher, bhutchings; +Cc: netdev
This change is meant to allow for nfc to insert and remove filters in order
to test the ethtool interface which includes it's own rules manager.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---
drivers/net/ixgbe/ixgbe_ethtool.c | 232 +++++++++++++++++++++++++++++++++++++
drivers/net/ixgbe/ixgbe_main.c | 45 +++++++
2 files changed, 277 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 145e018..a91e8db 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -2453,6 +2453,237 @@ static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
return ret;
}
+static int ixgbe_update_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
+ struct ixgbe_fdir_filter *input,
+ u16 sw_idx)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct hlist_node *node, *node2, *parent;
+ struct ixgbe_fdir_filter *rule;
+ int err = -EINVAL;
+
+ parent = NULL;
+ rule = NULL;
+
+ hlist_for_each_entry_safe(rule, node, node2,
+ &adapter->fdir_filter_list, fdir_node) {
+ /* hash found, or no matching entry */
+ if (rule->sw_idx >= sw_idx)
+ break;
+ parent = node;
+ }
+
+ /* if there is an old rule occupying our place remove it */
+ if (rule && (rule->sw_idx == sw_idx)) {
+ if (!input || (rule->filter.formatted.bkt_hash !=
+ input->filter.formatted.bkt_hash)) {
+ err = ixgbe_fdir_erase_perfect_filter_82599(hw,
+ &rule->filter,
+ sw_idx);
+ }
+
+ hlist_del(&rule->fdir_node);
+ kfree(rule);
+ adapter->fdir_filter_count--;
+ }
+
+ /* stop here if there was not an input filter provided */
+ if (!input)
+ return err;
+
+ /* reset error since we are now adding a filter */
+ err = 0;
+
+ /* initialize node and set software index */
+ INIT_HLIST_NODE(&input->fdir_node);
+
+ /* add filter to the list */
+ if (parent)
+ hlist_add_after(parent, &input->fdir_node);
+ else
+ hlist_add_head(&input->fdir_node,
+ &adapter->fdir_filter_list);
+
+ /* update counts */
+ adapter->fdir_filter_count++;
+
+ return err;
+}
+
+static int ixgbe_flowspec_to_flow_type(struct ethtool_rx_flow_spec *fsp,
+ u8 *flow_type)
+{
+ switch (fsp->flow_type) {
+ case TCP_V4_FLOW:
+ *flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
+ break;
+ case UDP_V4_FLOW:
+ *flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
+ break;
+ case SCTP_V4_FLOW:
+ *flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
+ break;
+ case IP_USER_FLOW:
+ switch (fsp->h_u.usr_ip4_spec.proto) {
+ case IPPROTO_TCP:
+ *flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
+ break;
+ case IPPROTO_UDP:
+ *flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
+ break;
+ case IPPROTO_SCTP:
+ *flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
+ break;
+ case 0:
+ if (!fsp->m_u.usr_ip4_spec.proto) {
+ *flow_type = IXGBE_ATR_FLOW_TYPE_IPV4;
+ break;
+ }
+ default:
+ return 0;
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static int ixgbe_add_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
+ struct ethtool_rxnfc *cmd)
+{
+ struct ethtool_rx_flow_spec *fsp =
+ (struct ethtool_rx_flow_spec *)&cmd->fs;
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct ixgbe_fdir_filter *input;
+ union ixgbe_atr_input mask;
+ int err;
+
+ if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
+ return -EOPNOTSUPP;
+
+ /*
+ * Don't allow programming if the action is a queue greater than
+ * the number of online Rx queues.
+ */
+ if ((fsp->ring_cookie != RX_CLS_FLOW_DISC) &&
+ (fsp->ring_cookie >= adapter->num_rx_queues))
+ return -EINVAL;
+
+ input = kzalloc(sizeof(*input), GFP_ATOMIC);
+ if (!input)
+ return -ENOMEM;
+
+ memset(&mask, 0, sizeof(union ixgbe_atr_input));
+
+ /* set SW index */
+ input->sw_idx = fsp->location;
+
+ /* record flow type */
+ if (!ixgbe_flowspec_to_flow_type(fsp,
+ &input->filter.formatted.flow_type)) {
+ e_err(drv, "Unrecognized flow type\n");
+ goto err_out;
+ }
+
+ mask.formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK |
+ IXGBE_ATR_L4TYPE_MASK;
+
+ if (input->filter.formatted.flow_type == IXGBE_ATR_FLOW_TYPE_IPV4)
+ mask.formatted.flow_type &= IXGBE_ATR_L4TYPE_IPV6_MASK;
+
+ /* Copy input into formatted structures */
+ input->filter.formatted.src_ip[0] = fsp->h_u.tcp_ip4_spec.ip4src;
+ mask.formatted.src_ip[0] = fsp->m_u.tcp_ip4_spec.ip4src;
+ input->filter.formatted.dst_ip[0] = fsp->h_u.tcp_ip4_spec.ip4dst;
+ mask.formatted.dst_ip[0] = fsp->m_u.tcp_ip4_spec.ip4dst;
+ input->filter.formatted.src_port = fsp->h_u.tcp_ip4_spec.psrc;
+ mask.formatted.src_port = fsp->m_u.tcp_ip4_spec.psrc;
+ input->filter.formatted.dst_port = fsp->h_u.tcp_ip4_spec.pdst;
+ mask.formatted.dst_port = fsp->m_u.tcp_ip4_spec.pdst;
+
+ /* determine if we need to drop or route the packet */
+ if (fsp->ring_cookie == RX_CLS_FLOW_DISC)
+ input->action = IXGBE_FDIR_DROP_QUEUE;
+ else
+ input->action = fsp->ring_cookie;
+
+ spin_lock(&adapter->fdir_perfect_lock);
+
+ if (hlist_empty(&adapter->fdir_filter_list)) {
+ /* save mask and program input mask into HW */
+ memcpy(&adapter->fdir_mask, &mask, sizeof(mask));
+ err = ixgbe_fdir_set_input_mask_82599(hw, &mask);
+ if (err) {
+ e_err(drv, "Error writing mask\n");
+ goto err_out_w_lock;
+ }
+ } else if (memcmp(&adapter->fdir_mask, &mask, sizeof(mask))) {
+ e_err(drv, "Only one mask supported per port\n");
+ goto err_out_w_lock;
+ }
+
+ /* apply mask and compute/store hash */
+ ixgbe_atr_compute_perfect_hash_82599(&input->filter, &mask);
+
+ /* Don't exceed the available space for filters in the HW */
+ if (adapter->fdir_filter_count >=
+ ((1024 << adapter->fdir_pballoc) - 2))
+ goto err_out_w_lock;
+
+ /* program filters to filter memory */
+ err = ixgbe_fdir_write_perfect_filter_82599(hw,
+ &input->filter, input->sw_idx,
+ adapter->rx_ring[input->action]->reg_idx);
+ if (err)
+ goto err_out_w_lock;
+
+ ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
+
+ spin_unlock(&adapter->fdir_perfect_lock);
+
+ return err;
+err_out_w_lock:
+ spin_unlock(&adapter->fdir_perfect_lock);
+err_out:
+ kfree(input);
+ return -1;
+}
+
+static int ixgbe_del_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
+ struct ethtool_rxnfc *cmd)
+{
+ struct ethtool_rx_flow_spec *fsp =
+ (struct ethtool_rx_flow_spec *)&cmd->fs;
+ int err;
+
+ spin_lock(&adapter->fdir_perfect_lock);
+ err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, fsp->location);
+ spin_unlock(&adapter->fdir_perfect_lock);
+
+ return err;
+}
+
+static int ixgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ int ret = -EOPNOTSUPP;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_SRXCLSRLINS:
+ ret = ixgbe_add_ethtool_fdir_entry(adapter, cmd);
+ break;
+ case ETHTOOL_SRXCLSRLDEL:
+ ret = ixgbe_del_ethtool_fdir_entry(adapter, cmd);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
static const struct ethtool_ops ixgbe_ethtool_ops = {
.get_settings = ixgbe_get_settings,
.set_settings = ixgbe_set_settings,
@@ -2489,6 +2720,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
.get_flags = ethtool_op_get_flags,
.set_flags = ixgbe_set_flags,
.get_rxnfc = ixgbe_get_rxnfc,
+ .set_rxnfc = ixgbe_set_rxnfc,
};
void ixgbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 6b6f602..bd79ac1 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -3667,6 +3667,28 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
}
#endif
+static void ixgbe_fdir_filter_restore(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct hlist_node *node, *node2;
+ struct ixgbe_fdir_filter *filter;
+
+ spin_lock(&adapter->fdir_perfect_lock);
+
+ if (!hlist_empty(&adapter->fdir_filter_list))
+ ixgbe_fdir_set_input_mask_82599(hw, &adapter->fdir_mask);
+
+ hlist_for_each_entry_safe(filter, node, node2,
+ &adapter->fdir_filter_list, fdir_node) {
+ ixgbe_fdir_write_perfect_filter_82599(hw,
+ &filter->filter,
+ filter->sw_idx,
+ filter->action);
+ }
+
+ spin_unlock(&adapter->fdir_perfect_lock);
+}
+
static void ixgbe_configure(struct ixgbe_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
@@ -3690,6 +3712,10 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
adapter->tx_ring[i]->atr_sample_rate =
adapter->atr_sample_rate;
ixgbe_init_fdir_signature_82599(hw, adapter->fdir_pballoc);
+ } else if (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) {
+ ixgbe_init_fdir_perfect_82599(&adapter->hw,
+ adapter->fdir_pballoc);
+ ixgbe_fdir_filter_restore(adapter);
}
ixgbe_configure_virtualization(adapter);
@@ -4075,6 +4101,23 @@ static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter)
ixgbe_clean_tx_ring(adapter->tx_ring[i]);
}
+static void ixgbe_fdir_filter_exit(struct ixgbe_adapter *adapter)
+{
+ struct hlist_node *node, *node2;
+ struct ixgbe_fdir_filter *filter;
+
+ spin_lock(&adapter->fdir_perfect_lock);
+
+ hlist_for_each_entry_safe(filter, node, node2,
+ &adapter->fdir_filter_list, fdir_node) {
+ hlist_del(&filter->fdir_node);
+ kfree(filter);
+ }
+ adapter->fdir_filter_count = 0;
+
+ spin_unlock(&adapter->fdir_perfect_lock);
+}
+
void ixgbe_down(struct ixgbe_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
@@ -5534,6 +5577,8 @@ static int ixgbe_close(struct net_device *netdev)
ixgbe_down(adapter);
ixgbe_free_irq(adapter);
+ ixgbe_fdir_filter_exit(adapter);
+
ixgbe_free_all_tx_resources(adapter);
ixgbe_free_all_rx_resources(adapter);
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [net-next-2.6 PATCH 10/10] [RFC] ixgbe: Add support for using the same fields as ntuple in nfc
2011-02-25 23:32 [net-next-2.6 PATCH 00/10] Workarounds and fixes for ntuple filters Alexander Duyck
` (8 preceding siblings ...)
2011-02-25 23:33 ` [net-next-2.6 PATCH 09/10] [RFC] ixgbe: add support for nfc addition and removal of filters Alexander Duyck
@ 2011-02-25 23:33 ` Alexander Duyck
9 siblings, 0 replies; 24+ messages in thread
From: Alexander Duyck @ 2011-02-25 23:33 UTC (permalink / raw)
To: davem, jeffrey.t.kirsher, bhutchings; +Cc: netdev
This change is meant to make use of the NTUPLE_FLOW_EXT to allow the
network flow classifier interface to support the same type of options in
terms of VLAN and User-defined as the ntuple interface.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---
drivers/net/ixgbe/ixgbe_ethtool.c | 19 +++++++++++++++++++
1 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index a91e8db..494e1bf 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -2388,6 +2388,13 @@ static int ixgbe_get_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
fsp->m_u.tcp_ip4_spec.ip4src = mask->formatted.src_ip[0];
fsp->h_u.tcp_ip4_spec.ip4dst = rule->filter.formatted.dst_ip[0];
fsp->m_u.tcp_ip4_spec.ip4dst = mask->formatted.dst_ip[0];
+ fsp->h_u.ntuple_spec.vlan_tci = rule->filter.formatted.vlan_id;
+ fsp->m_u.ntuple_spec.vlan_tci = mask->formatted.vlan_id;
+ fsp->h_u.ntuple_spec.vlan_etype = rule->filter.formatted.flex_bytes;
+ fsp->m_u.ntuple_spec.vlan_etype = mask->formatted.flex_bytes;
+ *(u8 *)fsp->h_u.ntuple_spec.data = rule->filter.formatted.vm_pool;
+ *(u8 *)fsp->m_u.ntuple_spec.data = mask->formatted.vm_pool;
+ fsp->flow_type_ext = NTUPLE_FLOW_EXT;
/* record action */
if (rule->action == IXGBE_FDIR_DROP_QUEUE)
@@ -2603,6 +2610,18 @@ static int ixgbe_add_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
input->filter.formatted.dst_port = fsp->h_u.tcp_ip4_spec.pdst;
mask.formatted.dst_port = fsp->m_u.tcp_ip4_spec.pdst;
+ if (fsp->flow_type_ext == NTUPLE_FLOW_EXT) {
+ input->filter.formatted.vm_pool =
+ *(unsigned char *)fsp->h_u.ntuple_spec.data;
+ mask.formatted.vm_pool =
+ *(unsigned char *)fsp->m_u.ntuple_spec.data;
+ input->filter.formatted.vlan_id = fsp->h_u.ntuple_spec.vlan_tci;
+ mask.formatted.vlan_id = fsp->m_u.ntuple_spec.vlan_tci;
+ input->filter.formatted.flex_bytes =
+ fsp->h_u.ntuple_spec.vlan_etype;
+ mask.formatted.flex_bytes = fsp->m_u.ntuple_spec.vlan_etype;
+ }
+
/* determine if we need to drop or route the packet */
if (fsp->ring_cookie == RX_CLS_FLOW_DISC)
input->action = IXGBE_FDIR_DROP_QUEUE;
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [net-next-2.6 PATCH 01/10] ethtool: prevent null pointer dereference with NTUPLE set but no set_rx_ntuple
2011-02-25 23:32 ` [net-next-2.6 PATCH 01/10] ethtool: prevent null pointer dereference with NTUPLE set but no set_rx_ntuple Alexander Duyck
@ 2011-02-26 0:21 ` Ben Hutchings
2011-02-26 0:40 ` Alexander Duyck
0 siblings, 1 reply; 24+ messages in thread
From: Ben Hutchings @ 2011-02-26 0:21 UTC (permalink / raw)
To: Alexander Duyck; +Cc: davem, jeffrey.t.kirsher, netdev
On Fri, 2011-02-25 at 15:32 -0800, Alexander Duyck wrote:
> This change is meant to prevent a possible null pointer dereference if
> NETIF_F_NTUPLE is defined but the set_rx_ntuple function pointer is not.
I think it would be a bug for NETIF_F_NTUPLE to be enabled on a device
that doesn't have this operation. Are there any drivers for which this
is possible?
> This issue appears to affect all kernels since 2.6.34.
If this can actually happen, the fix should go to net-2.6 and
stable@kernel.org. However, I think that the null deference is
impossible and this really just fixes the error code.
Ben.
> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
> ---
>
> net/core/ethtool.c | 3 +++
> 1 files changed, 3 insertions(+), 0 deletions(-)
>
> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
> index c1a71bb..4843674 100644
> --- a/net/core/ethtool.c
> +++ b/net/core/ethtool.c
> @@ -893,6 +893,9 @@ static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev,
> struct ethtool_rx_ntuple_flow_spec_container *fsc = NULL;
> int ret;
>
> + if (!ops->set_rx_ntuple)
> + return -EOPNOTSUPP;
> +
> if (!(dev->features & NETIF_F_NTUPLE))
> return -EINVAL;
>
>
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [net-next-2.6 PATCH 01/10] ethtool: prevent null pointer dereference with NTUPLE set but no set_rx_ntuple
2011-02-26 0:21 ` Ben Hutchings
@ 2011-02-26 0:40 ` Alexander Duyck
2011-02-27 0:07 ` David Miller
0 siblings, 1 reply; 24+ messages in thread
From: Alexander Duyck @ 2011-02-26 0:40 UTC (permalink / raw)
To: Ben Hutchings
Cc: davem@davemloft.net, Kirsher, Jeffrey T, netdev@vger.kernel.org
On 2/25/2011 4:21 PM, Ben Hutchings wrote:
> On Fri, 2011-02-25 at 15:32 -0800, Alexander Duyck wrote:
>> This change is meant to prevent a possible null pointer dereference if
>> NETIF_F_NTUPLE is defined but the set_rx_ntuple function pointer is not.
>
> I think it would be a bug for NETIF_F_NTUPLE to be enabled on a device
> that doesn't have this operation. Are there any drivers for which this
> is possible?
Currently there are no drivers where this is possible. However I
encountered it as a result of testing the patches further on in this set.
>> This issue appears to affect all kernels since 2.6.34.
>
> If this can actually happen, the fix should go to net-2.6 and
> stable@kernel.org. However, I think that the null deference is
> impossible and this really just fixes the error code.
>
> Ben.
It cannot occur with any of the in-kernel drivers since they all set the
NETIF_F_NTUPLE flag and have the function defined. However going
forward I would like to have the option of using the network flow
classifier interface instead of the set_rx_ntuple interface due to the
fact that it supports many of the features I needed.
I believe this patch should apply to net-2.6 without any changes so if
it is better placed there I will resubmit it specifically for net-2.6
and stable.
Thanks,
Alex
>> Signed-off-by: Alexander Duyck<alexander.h.duyck@intel.com>
>> ---
>>
>> net/core/ethtool.c | 3 +++
>> 1 files changed, 3 insertions(+), 0 deletions(-)
>>
>> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
>> index c1a71bb..4843674 100644
>> --- a/net/core/ethtool.c
>> +++ b/net/core/ethtool.c
>> @@ -893,6 +893,9 @@ static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev,
>> struct ethtool_rx_ntuple_flow_spec_container *fsc = NULL;
>> int ret;
>>
>> + if (!ops->set_rx_ntuple)
>> + return -EOPNOTSUPP;
>> +
>> if (!(dev->features& NETIF_F_NTUPLE))
>> return -EINVAL;
>>
>>
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [net-next-2.6 PATCH 02/10] ethtool: add ntuple flow specifier to network flow classifier
2011-02-25 23:32 ` [net-next-2.6 PATCH 02/10] ethtool: add ntuple flow specifier to network flow classifier Alexander Duyck
@ 2011-02-26 1:00 ` Ben Hutchings
2011-02-26 5:30 ` Alexander Duyck
2011-02-27 0:05 ` David Miller
1 sibling, 1 reply; 24+ messages in thread
From: Ben Hutchings @ 2011-02-26 1:00 UTC (permalink / raw)
To: Alexander Duyck; +Cc: davem, jeffrey.t.kirsher, netdev
On Fri, 2011-02-25 at 15:32 -0800, Alexander Duyck wrote:
> This change is meant to add an ntuple define type to the rx network flow
> classification specifiers. The idea is to allow ntuple to be displayed and
> possibly configured via the network flow classification interface. To do
> this I added a ntuple_flow_spec_ext to the lsit of supported filters, and
> added a flow_type_ext value to the structure in an unused hole within the
> ethtool_rx_flow_spec structure.
There's a hole there on 64-bit architectures. Unfortunately, on i386
and other architectures where u64 is not 64-bit-aligned, there isn't.
We actually need to add compat handling for the commands that use it.
Also, we don't want these flags to be ignored by older kernel versions
and drivers - they should reject specs that they don't understand. So
any extension flags need to be added to flow_type.
> Due to the fact that the flow specifier structures are only 4 byte aligned
> instead of 8 I had to break the user data field into 2 sections. In
> addition I added the vlan ethertype field since this is what ixgbe was
> using the user-data for currently and it allows for the fields to stay 4
> byte aligned while occupying space at the end of the flow_spec.
>
> In order to guarantee byte ordering I also thought it best to keep all
> fields in the flow_spec area a big endian value, as such I added vlan, vlan
> ethertype, and data as big endian values.
It's not important that byte order is consistent across architectures.
> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
> ---
>
> include/linux/ethtool.h | 20 ++++++++++++++++++++
> 1 files changed, 20 insertions(+), 0 deletions(-)
>
> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
> index aac3e2e..3d1f8e0 100644
> --- a/include/linux/ethtool.h
> +++ b/include/linux/ethtool.h
> @@ -378,10 +378,25 @@ struct ethtool_usrip4_spec {
> };
>
> /**
> + * struct ethtool_ntuple_spec_ext - flow spec extension for ntuple in nfc
> + * @unused: space unused by extension
> + * @vlan_etype: EtherType for vlan tagged packet to match
> + * @vlan_tci: VLAN tag to match
> + * @data: Driver-dependent data to match
> + */
> +struct ethtool_ntuple_spec_ext {
> + __be32 unused[15];
> + __be16 vlan_etype;
> + __be16 vlan_tci;
> + __be32 data[2];
> +};
[...]
This is a really nasty way to reclaim space in the union.
Let's name the union, shrink it and insert the extra fields that way:
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -377,27 +377,43 @@ struct ethtool_usrip4_spec {
__u8 proto;
};
+union ethtool_flow_union {
+ struct ethtool_tcpip4_spec tcp_ip4_spec;
+ struct ethtool_tcpip4_spec udp_ip4_spec;
+ struct ethtool_tcpip4_spec sctp_ip4_spec;
+ struct ethtool_ah_espip4_spec ah_ip4_spec;
+ struct ethtool_ah_espip4_spec esp_ip4_spec;
+ struct ethtool_usrip4_spec usr_ip4_spec;
+ struct ethhdr ether_spec;
+ __u8 hdata[52];
+};
+
+struct ethtool_flow_ext {
+ __be16 vlan_etype;
+ __be16 vlan_tci;
+ __be32 data[2];
+ __u32 reserved[2];
+};
+
/**
* struct ethtool_rx_flow_spec - specification for RX flow filter
* @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW
* @h_u: Flow fields to match (dependent on @flow_type)
+ * @h_ext: Additional fields to match
* @m_u: Masks for flow field bits to be ignored
+ * @m_ext: Masks for additional field bits to be ignored.
+ * Note, all additional fields must be ignored unless @flow_type
+ * includes the %FLOW_EXT flag.
* @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC
* if packets should be discarded
* @location: Index of filter in hardware table
*/
struct ethtool_rx_flow_spec {
__u32 flow_type;
- union {
- struct ethtool_tcpip4_spec tcp_ip4_spec;
- struct ethtool_tcpip4_spec udp_ip4_spec;
- struct ethtool_tcpip4_spec sctp_ip4_spec;
- struct ethtool_ah_espip4_spec ah_ip4_spec;
- struct ethtool_ah_espip4_spec esp_ip4_spec;
- struct ethtool_usrip4_spec usr_ip4_spec;
- struct ethhdr ether_spec;
- __u8 hdata[72];
- } h_u, m_u;
+ union ethtool_flow_union h_u;
+ struct ethtool_flow_ext h_ext;
+ union ethtool_flow_union m_u;
+ struct ethtool_flow_ext m_ext;
__u64 ring_cookie;
__u32 location;
};
@@ -954,6 +970,8 @@ struct ethtool_ops {
#define IPV4_FLOW 0x10 /* hash only */
#define IPV6_FLOW 0x11 /* hash only */
#define ETHER_FLOW 0x12 /* spec only (ether_spec) */
+/* Flag to enable additional fields in struct ethtool_rx_flow_spec */
+#define FLOW_EXT 0x80000000
/* L3-L4 network traffic flow hash options */
#define RXH_L2DA (1 << 1)
---
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [net-next-2.6 PATCH 02/10] ethtool: add ntuple flow specifier to network flow classifier
2011-02-26 1:00 ` Ben Hutchings
@ 2011-02-26 5:30 ` Alexander Duyck
2011-03-02 18:50 ` Ben Hutchings
0 siblings, 1 reply; 24+ messages in thread
From: Alexander Duyck @ 2011-02-26 5:30 UTC (permalink / raw)
To: Ben Hutchings; +Cc: Alexander Duyck, davem, jeffrey.t.kirsher, netdev
On Fri, Feb 25, 2011 at 5:00 PM, Ben Hutchings
<bhutchings@solarflare.com> wrote:
> On Fri, 2011-02-25 at 15:32 -0800, Alexander Duyck wrote:
>> This change is meant to add an ntuple define type to the rx network flow
>> classification specifiers. The idea is to allow ntuple to be displayed and
>> possibly configured via the network flow classification interface. To do
>> this I added a ntuple_flow_spec_ext to the lsit of supported filters, and
>> added a flow_type_ext value to the structure in an unused hole within the
>> ethtool_rx_flow_spec structure.
>
> There's a hole there on 64-bit architectures. Unfortunately, on i386
> and other architectures where u64 is not 64-bit-aligned, there isn't.
> We actually need to add compat handling for the commands that use it.
>
> Also, we don't want these flags to be ignored by older kernel versions
> and drivers - they should reject specs that they don't understand. So
> any extension flags need to be added to flow_type.
>
>> Due to the fact that the flow specifier structures are only 4 byte aligned
>> instead of 8 I had to break the user data field into 2 sections. In
>> addition I added the vlan ethertype field since this is what ixgbe was
>> using the user-data for currently and it allows for the fields to stay 4
>> byte aligned while occupying space at the end of the flow_spec.
>>
>> In order to guarantee byte ordering I also thought it best to keep all
>> fields in the flow_spec area a big endian value, as such I added vlan, vlan
>> ethertype, and data as big endian values.
>
> It's not important that byte order is consistent across architectures.
>
>> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
>> ---
>>
>> include/linux/ethtool.h | 20 ++++++++++++++++++++
>> 1 files changed, 20 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
>> index aac3e2e..3d1f8e0 100644
>> --- a/include/linux/ethtool.h
>> +++ b/include/linux/ethtool.h
>> @@ -378,10 +378,25 @@ struct ethtool_usrip4_spec {
>> };
>>
>> /**
>> + * struct ethtool_ntuple_spec_ext - flow spec extension for ntuple in nfc
>> + * @unused: space unused by extension
>> + * @vlan_etype: EtherType for vlan tagged packet to match
>> + * @vlan_tci: VLAN tag to match
>> + * @data: Driver-dependent data to match
>> + */
>> +struct ethtool_ntuple_spec_ext {
>> + __be32 unused[15];
>> + __be16 vlan_etype;
>> + __be16 vlan_tci;
>> + __be32 data[2];
>> +};
> [...]
>
> This is a really nasty way to reclaim space in the union.
>
> Let's name the union, shrink it and insert the extra fields that way:
>
> --- a/include/linux/ethtool.h
> +++ b/include/linux/ethtool.h
> @@ -377,27 +377,43 @@ struct ethtool_usrip4_spec {
> __u8 proto;
> };
>
> +union ethtool_flow_union {
> + struct ethtool_tcpip4_spec tcp_ip4_spec;
> + struct ethtool_tcpip4_spec udp_ip4_spec;
> + struct ethtool_tcpip4_spec sctp_ip4_spec;
> + struct ethtool_ah_espip4_spec ah_ip4_spec;
> + struct ethtool_ah_espip4_spec esp_ip4_spec;
> + struct ethtool_usrip4_spec usr_ip4_spec;
> + struct ethhdr ether_spec;
> + __u8 hdata[52];
> +};
> +
> +struct ethtool_flow_ext {
> + __be16 vlan_etype;
> + __be16 vlan_tci;
> + __be32 data[2];
> + __u32 reserved[2];
> +};
> +
Any chance of getting the reserved fields moved to the top of the
structure? My only concern is that we might end up with a flow spec
larger than 52 bytes at some point and moving the reserved fields to
the front might give us a little more wiggle room future
compatibility.
> /**
> * struct ethtool_rx_flow_spec - specification for RX flow filter
> * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW
> * @h_u: Flow fields to match (dependent on @flow_type)
> + * @h_ext: Additional fields to match
> * @m_u: Masks for flow field bits to be ignored
> + * @m_ext: Masks for additional field bits to be ignored.
> + * Note, all additional fields must be ignored unless @flow_type
> + * includes the %FLOW_EXT flag.
> * @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC
> * if packets should be discarded
> * @location: Index of filter in hardware table
> */
> struct ethtool_rx_flow_spec {
> __u32 flow_type;
> - union {
> - struct ethtool_tcpip4_spec tcp_ip4_spec;
> - struct ethtool_tcpip4_spec udp_ip4_spec;
> - struct ethtool_tcpip4_spec sctp_ip4_spec;
> - struct ethtool_ah_espip4_spec ah_ip4_spec;
> - struct ethtool_ah_espip4_spec esp_ip4_spec;
> - struct ethtool_usrip4_spec usr_ip4_spec;
> - struct ethhdr ether_spec;
> - __u8 hdata[72];
> - } h_u, m_u;
> + union ethtool_flow_union h_u;
> + struct ethtool_flow_ext h_ext;
> + union ethtool_flow_union m_u;
> + struct ethtool_flow_ext m_ext;
> __u64 ring_cookie;
> __u32 location;
> };
> @@ -954,6 +970,8 @@ struct ethtool_ops {
> #define IPV4_FLOW 0x10 /* hash only */
> #define IPV6_FLOW 0x11 /* hash only */
> #define ETHER_FLOW 0x12 /* spec only (ether_spec) */
> +/* Flag to enable additional fields in struct ethtool_rx_flow_spec */
> +#define FLOW_EXT 0x80000000
>
> /* L3-L4 network traffic flow hash options */
> #define RXH_L2DA (1 << 1)
> ---
>
> Ben.
This works for my purposes other than the one comment above. However
if you are fine with it I am good with it since I can't think of any
filters that we might need in the near future that would require more
than 52 bytes.
Acked-by: Alexander Duyck <alexander.h.duyck@intel.com>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [net-next-2.6 PATCH 02/10] ethtool: add ntuple flow specifier to network flow classifier
2011-02-25 23:32 ` [net-next-2.6 PATCH 02/10] ethtool: add ntuple flow specifier to network flow classifier Alexander Duyck
2011-02-26 1:00 ` Ben Hutchings
@ 2011-02-27 0:05 ` David Miller
1 sibling, 0 replies; 24+ messages in thread
From: David Miller @ 2011-02-27 0:05 UTC (permalink / raw)
To: alexander.h.duyck; +Cc: jeffrey.t.kirsher, bhutchings, netdev
From: Alexander Duyck <alexander.h.duyck@intel.com>
Date: Fri, 25 Feb 2011 15:32:49 -0800
> @@ -396,8 +411,10 @@ struct ethtool_rx_flow_spec {
> struct ethtool_ah_espip4_spec esp_ip4_spec;
> struct ethtool_usrip4_spec usr_ip4_spec;
> struct ethhdr ether_spec;
> + struct ethtool_ntuple_spec_ext ntuple_spec;
> __u8 hdata[72];
> } h_u, m_u;
> + __u32 flow_type_ext;
> __u64 ring_cookie;
> __u32 location;
> };
How can you add this flow_type_ext member to this user visible structure
without utterly breaking userspace? It changes the offsets of the
ring_cookie and location members.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [net-next-2.6 PATCH 01/10] ethtool: prevent null pointer dereference with NTUPLE set but no set_rx_ntuple
2011-02-26 0:40 ` Alexander Duyck
@ 2011-02-27 0:07 ` David Miller
2011-02-27 2:16 ` Alexander Duyck
0 siblings, 1 reply; 24+ messages in thread
From: David Miller @ 2011-02-27 0:07 UTC (permalink / raw)
To: alexander.h.duyck; +Cc: bhutchings, jeffrey.t.kirsher, netdev
From: Alexander Duyck <alexander.h.duyck@intel.com>
Date: Fri, 25 Feb 2011 16:40:13 -0800
> It cannot occur with any of the in-kernel drivers since they all set
> the NETIF_F_NTUPLE flag and have the function defined. However going
> forward I would like to have the option of using the network flow
> classifier interface instead of the set_rx_ntuple interface due to the
> fact that it supports many of the features I needed.
This still doesn't explain to me why a driver would set the feature
flag, but not actually implement the feature.
I'm not applying this patch.
When you create the situation that causes the potentially NULL
dereference, then you can use that patch to show why this seemingly
illogical situation can indeed occur.
Until then no driver causes this issue, therefore the problem does
not exist.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [net-next-2.6 PATCH 01/10] ethtool: prevent null pointer dereference with NTUPLE set but no set_rx_ntuple
2011-02-27 0:07 ` David Miller
@ 2011-02-27 2:16 ` Alexander Duyck
0 siblings, 0 replies; 24+ messages in thread
From: Alexander Duyck @ 2011-02-27 2:16 UTC (permalink / raw)
To: David Miller; +Cc: alexander.h.duyck, bhutchings, jeffrey.t.kirsher, netdev
On Sat, Feb 26, 2011 at 4:07 PM, David Miller <davem@davemloft.net> wrote:
> From: Alexander Duyck <alexander.h.duyck@intel.com>
> Date: Fri, 25 Feb 2011 16:40:13 -0800
>
>> It cannot occur with any of the in-kernel drivers since they all set
>> the NETIF_F_NTUPLE flag and have the function defined. However going
>> forward I would like to have the option of using the network flow
>> classifier interface instead of the set_rx_ntuple interface due to the
>> fact that it supports many of the features I needed.
>
> This still doesn't explain to me why a driver would set the feature
> flag, but not actually implement the feature.
Actually the reason I ran into this is because of the patches in the
RFC set. Basically I was looking at moving the ntuple support in
ixgbe over to network flow classifier rules. As such I was leaving
the ntuple flag set, but using set_rxnfc via the filter rules instead.
If you recommend adding a new flag to do that I am fine with that.
> I'm not applying this patch.
>
> When you create the situation that causes the potentially NULL
> dereference, then you can use that patch to show why this seemingly
> illogical situation can indeed occur.
>
> Until then no driver causes this issue, therefore the problem does
> not exist.
I'll do some digging late next week to see if there are any other
means of encountering the issue and will get back to you if I find
anything.
Thanks,
Alex
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [net-next-2.6 PATCH 02/10] ethtool: add ntuple flow specifier to network flow classifier
2011-02-26 5:30 ` Alexander Duyck
@ 2011-03-02 18:50 ` Ben Hutchings
2011-03-02 19:11 ` Dimitrios Michailidis
2011-03-04 21:00 ` Alexander Duyck
0 siblings, 2 replies; 24+ messages in thread
From: Ben Hutchings @ 2011-03-02 18:50 UTC (permalink / raw)
To: Alexander Duyck; +Cc: Alexander Duyck, davem, jeffrey.t.kirsher, netdev
On Fri, 2011-02-25 at 21:30 -0800, Alexander Duyck wrote:
> On Fri, Feb 25, 2011 at 5:00 PM, Ben Hutchings
> <bhutchings@solarflare.com> wrote:
> > On Fri, 2011-02-25 at 15:32 -0800, Alexander Duyck wrote:
[...]
> >> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
> >> index aac3e2e..3d1f8e0 100644
> >> --- a/include/linux/ethtool.h
> >> +++ b/include/linux/ethtool.h
> >> @@ -378,10 +378,25 @@ struct ethtool_usrip4_spec {
> >> };
> >>
> >> /**
> >> + * struct ethtool_ntuple_spec_ext - flow spec extension for ntuple in nfc
> >> + * @unused: space unused by extension
> >> + * @vlan_etype: EtherType for vlan tagged packet to match
> >> + * @vlan_tci: VLAN tag to match
> >> + * @data: Driver-dependent data to match
> >> + */
> >> +struct ethtool_ntuple_spec_ext {
> >> + __be32 unused[15];
> >> + __be16 vlan_etype;
> >> + __be16 vlan_tci;
> >> + __be32 data[2];
> >> +};
> > [...]
> >
> > This is a really nasty way to reclaim space in the union.
> >
> > Let's name the union, shrink it and insert the extra fields that way:
> >
> > --- a/include/linux/ethtool.h
> > +++ b/include/linux/ethtool.h
> > @@ -377,27 +377,43 @@ struct ethtool_usrip4_spec {
> > __u8 proto;
> > };
> >
> > +union ethtool_flow_union {
> > + struct ethtool_tcpip4_spec tcp_ip4_spec;
> > + struct ethtool_tcpip4_spec udp_ip4_spec;
> > + struct ethtool_tcpip4_spec sctp_ip4_spec;
> > + struct ethtool_ah_espip4_spec ah_ip4_spec;
> > + struct ethtool_ah_espip4_spec esp_ip4_spec;
> > + struct ethtool_usrip4_spec usr_ip4_spec;
> > + struct ethhdr ether_spec;
> > + __u8 hdata[52];
> > +};
> > +
> > +struct ethtool_flow_ext {
> > + __be16 vlan_etype;
> > + __be16 vlan_tci;
> > + __be32 data[2];
> > + __u32 reserved[2];
> > +};
> > +
>
> Any chance of getting the reserved fields moved to the top of the
> structure? My only concern is that we might end up with a flow spec
> larger than 52 bytes at some point and moving the reserved fields to
> the front might give us a little more wiggle room future
> compatibility.
[...]
OK, so how about this:
/**
* union ethtool_flow_union - flow spec type-specific fields
* @tcp_ip4_spec: TCP/IPv4 fields to match
* @udp_ip4_spec: UDP/IPv4 fields to match
* @sctp_ip4_spec: SCTP/IPv4 fields to match
* @ah_ip4_spec: AH/IPv4 fields to match
* @esp_ip4_spec: ESP/IPv4 fields to match
* @usr_ip4_spec: User-defined IPv4 fields to match
* @ether_spec: Ethernet fields to match
*
* Note: The size of this union may shrink in future to allow for
* expansion in &struct ethtool_flow_ext.
*/
union ethtool_flow_union {
struct ethtool_tcpip4_spec tcp_ip4_spec;
struct ethtool_tcpip4_spec udp_ip4_spec;
struct ethtool_tcpip4_spec sctp_ip4_spec;
struct ethtool_ah_espip4_spec ah_ip4_spec;
struct ethtool_ah_espip4_spec esp_ip4_spec;
struct ethtool_usrip4_spec usr_ip4_spec;
struct ethhdr ether_spec;
__u8 hdata[60];
};
/**
* struct ethtool_flow_ext - flow spec common extension fields
* @vlan_etype: EtherType for vlan tagged packet to match
* @vlan_tci: VLAN tag to match
* @data: Driver-dependent data to match
*
* Note: Additional fields may be inserted before @vlan_etype in future,
* but the offset of the existing fields within the containing structure
* (&struct ethtool_rx_flow_spec) will be stable.
*/
struct ethtool_flow_ext {
__be16 vlan_etype;
__be16 vlan_tci;
__be32 data[2];
};
Please can you check that these definitions won't affect the size of
struct ethtool_rx_flow_spec on i386 or x86-64?
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [net-next-2.6 PATCH 02/10] ethtool: add ntuple flow specifier to network flow classifier
2011-03-02 18:50 ` Ben Hutchings
@ 2011-03-02 19:11 ` Dimitrios Michailidis
2011-03-02 19:27 ` Ben Hutchings
2011-03-04 21:00 ` Alexander Duyck
1 sibling, 1 reply; 24+ messages in thread
From: Dimitrios Michailidis @ 2011-03-02 19:11 UTC (permalink / raw)
To: Ben Hutchings, Alexander Duyck
Cc: Alexander Duyck, davem, jeffrey.t.kirsher, netdev
Ben Hutchings wrote:
> /**
> * struct ethtool_flow_ext - flow spec common extension fields
> * @vlan_etype: EtherType for vlan tagged packet to match
> * @vlan_tci: VLAN tag to match
> * @data: Driver-dependent data to match
> *
> * Note: Additional fields may be inserted before @vlan_etype in future,
> * but the offset of the existing fields within the containing structure
> * (&struct ethtool_rx_flow_spec) will be stable.
> */
> struct ethtool_flow_ext {
> __be16 vlan_etype;
> __be16 vlan_tci;
> __be32 data[2];
> };
I am wondering about the semantics of these vlan_* fields. Is vlan_etype the
Ethertype in the VLAN header or the type after it? Specifically, I am wondering
whether these fields are limited to VLANs or can work with general Ethertypes and the
2 bytes after them.
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [net-next-2.6 PATCH 02/10] ethtool: add ntuple flow specifier to network flow classifier
2011-03-02 19:11 ` Dimitrios Michailidis
@ 2011-03-02 19:27 ` Ben Hutchings
2011-03-02 20:03 ` Dimitrios Michailidis
0 siblings, 1 reply; 24+ messages in thread
From: Ben Hutchings @ 2011-03-02 19:27 UTC (permalink / raw)
To: Dimitrios Michailidis
Cc: Alexander Duyck, Alexander Duyck, davem, jeffrey.t.kirsher,
netdev
On Wed, 2011-03-02 at 11:11 -0800, Dimitrios Michailidis wrote:
> Ben Hutchings wrote:
> > /**
> > * struct ethtool_flow_ext - flow spec common extension fields
> > * @vlan_etype: EtherType for vlan tagged packet to match
> > * @vlan_tci: VLAN tag to match
> > * @data: Driver-dependent data to match
> > *
> > * Note: Additional fields may be inserted before @vlan_etype in future,
> > * but the offset of the existing fields within the containing structure
> > * (&struct ethtool_rx_flow_spec) will be stable.
> > */
> > struct ethtool_flow_ext {
> > __be16 vlan_etype;
> > __be16 vlan_tci;
> > __be32 data[2];
> > };
>
> I am wondering about the semantics of these vlan_* fields. Is vlan_etype the
> Ethertype in the VLAN header or the type after it?
It would be the the type in the VLAN tag. The nested ethertype is
normally implied by flow_type to be ETH_P_IP.
This does leave the question of what this would mean:
struct ethtool_rx_flow_spec fs = {
.flow_type = ... | FLOW_EXT,
...
.h_ext.vlan_tci = htons(0x1234),
.m_ext.vlan_etype = 0xffff,
};
This says the TCI must be == 0x1234 but the type can be anything. But
the type surely has to be be one assigned for use in VLAN tags. Should
we leave it to the driver/hardware to determine what those valid types
are, or should we reject this as valid?
> Specifically, I am wondering
> whether these fields are limited to VLANs or can work with general Ethertypes and the
> 2 bytes after them.
If you set flow_type = ETHER_FLOW you can then specify any combination
of Ethernet header fields to match in {h_u,m_u}.ether_spec. However, so
far only sfc implements it and it only allows matching on the
destination MAC address.
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [net-next-2.6 PATCH 02/10] ethtool: add ntuple flow specifier to network flow classifier
2011-03-02 19:27 ` Ben Hutchings
@ 2011-03-02 20:03 ` Dimitrios Michailidis
2011-03-04 19:30 ` Alexander Duyck
0 siblings, 1 reply; 24+ messages in thread
From: Dimitrios Michailidis @ 2011-03-02 20:03 UTC (permalink / raw)
To: Ben Hutchings
Cc: Alexander Duyck, Alexander Duyck, davem, jeffrey.t.kirsher,
netdev
Ben Hutchings wrote:
> On Wed, 2011-03-02 at 11:11 -0800, Dimitrios Michailidis wrote:
> > Ben Hutchings wrote:
> > > /**
> > > * struct ethtool_flow_ext - flow spec common extension fields
> > > * @vlan_etype: EtherType for vlan tagged packet to match
> > > * @vlan_tci: VLAN tag to match
> > > * @data: Driver-dependent data to match
> > > *
> > > * Note: Additional fields may be inserted before @vlan_etype in future,
> > > * but the offset of the existing fields within the containing structure
> > > * (&struct ethtool_rx_flow_spec) will be stable.
> > > */
> > > struct ethtool_flow_ext {
> > > __be16 vlan_etype;
> > > __be16 vlan_tci;
> > > __be32 data[2];
> > > };
> >
> > I am wondering about the semantics of these vlan_* fields. Is vlan_etype the
> > Ethertype in the VLAN header or the type after it?
>
> It would be the the type in the VLAN tag. The nested ethertype is
> normally implied by flow_type to be ETH_P_IP.
>
> This does leave the question of what this would mean:
>
> struct ethtool_rx_flow_spec fs = {
> .flow_type = ... | FLOW_EXT,
> ...
> .h_ext.vlan_tci = htons(0x1234),
> .m_ext.vlan_etype = 0xffff,
> };
>
> This says the TCI must be == 0x1234 but the type can be anything. But
> the type surely has to be be one assigned for use in VLAN tags. Should
> we leave it to the driver/hardware to determine what those valid types
> are, or should we reject this as valid?
Right. Devices have some internal rules for what qualifies as a VLAN frame.
If users are given the option to specify vlan_etype what do they get?
At least we need to specify what is expected so drivers can decide if they can support it.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [net-next-2.6 PATCH 02/10] ethtool: add ntuple flow specifier to network flow classifier
2011-03-02 20:03 ` Dimitrios Michailidis
@ 2011-03-04 19:30 ` Alexander Duyck
0 siblings, 0 replies; 24+ messages in thread
From: Alexander Duyck @ 2011-03-04 19:30 UTC (permalink / raw)
To: Dimitrios Michailidis
Cc: Ben Hutchings, Alexander Duyck, davem@davemloft.net,
Kirsher, Jeffrey T, netdev@vger.kernel.org
On 3/2/2011 12:03 PM, Dimitrios Michailidis wrote:
> Ben Hutchings wrote:
>> On Wed, 2011-03-02 at 11:11 -0800, Dimitrios Michailidis wrote:
>>> Ben Hutchings wrote:
>>>> /**
>>>> * struct ethtool_flow_ext - flow spec common extension fields
>>>> * @vlan_etype: EtherType for vlan tagged packet to match
>>>> * @vlan_tci: VLAN tag to match
>>>> * @data: Driver-dependent data to match
>>>> *
>>>> * Note: Additional fields may be inserted before @vlan_etype in future,
>>>> * but the offset of the existing fields within the containing structure
>>>> * (&struct ethtool_rx_flow_spec) will be stable.
>>>> */
>>>> struct ethtool_flow_ext {
>>>> __be16 vlan_etype;
>>>> __be16 vlan_tci;
>>>> __be32 data[2];
>>>> };
>>>
>>> I am wondering about the semantics of these vlan_* fields. Is vlan_etype the
>>> Ethertype in the VLAN header or the type after it?
>>
>> It would be the the type in the VLAN tag. The nested ethertype is
>> normally implied by flow_type to be ETH_P_IP.
>>
>> This does leave the question of what this would mean:
>>
>> struct ethtool_rx_flow_spec fs = {
>> .flow_type = ... | FLOW_EXT,
>> ...
>> .h_ext.vlan_tci = htons(0x1234),
>> .m_ext.vlan_etype = 0xffff,
>> };
>>
>> This says the TCI must be == 0x1234 but the type can be anything. But
>> the type surely has to be be one assigned for use in VLAN tags. Should
>> we leave it to the driver/hardware to determine what those valid types
>> are, or should we reject this as valid?
>
> Right. Devices have some internal rules for what qualifies as a VLAN frame.
> If users are given the option to specify vlan_etype what do they get?
> At least we need to specify what is expected so drivers can decide if they can support it.
The basic idea I had is similar to what Ben described. Basically the
vlan_etype can be used to determine the Ethertype for the VLAN to be
compared. The reason for this is specifically the VLAN 0 case since
without the VLAN Ethertype check VLAN 0 on ixgbe hardware will match an
untagged frame and that may not be a desired result. As such we can
specify the VLAN Ethertype and then we will only match VLAN tagged
frames without any false hits.
Thanks,
Alex
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [net-next-2.6 PATCH 02/10] ethtool: add ntuple flow specifier to network flow classifier
2011-03-02 18:50 ` Ben Hutchings
2011-03-02 19:11 ` Dimitrios Michailidis
@ 2011-03-04 21:00 ` Alexander Duyck
1 sibling, 0 replies; 24+ messages in thread
From: Alexander Duyck @ 2011-03-04 21:00 UTC (permalink / raw)
To: Ben Hutchings
Cc: Alexander Duyck, davem@davemloft.net, Kirsher, Jeffrey T,
netdev@vger.kernel.org
On 3/2/2011 10:50 AM, Ben Hutchings wrote:
> On Fri, 2011-02-25 at 21:30 -0800, Alexander Duyck wrote:
>> On Fri, Feb 25, 2011 at 5:00 PM, Ben Hutchings
>> <bhutchings@solarflare.com> wrote:
>>> On Fri, 2011-02-25 at 15:32 -0800, Alexander Duyck wrote:
> [...]
>>>> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
>>>> index aac3e2e..3d1f8e0 100644
>>>> --- a/include/linux/ethtool.h
>>>> +++ b/include/linux/ethtool.h
>>>> @@ -378,10 +378,25 @@ struct ethtool_usrip4_spec {
>>>> };
>>>>
>>>> /**
>>>> + * struct ethtool_ntuple_spec_ext - flow spec extension for ntuple in nfc
>>>> + * @unused: space unused by extension
>>>> + * @vlan_etype: EtherType for vlan tagged packet to match
>>>> + * @vlan_tci: VLAN tag to match
>>>> + * @data: Driver-dependent data to match
>>>> + */
>>>> +struct ethtool_ntuple_spec_ext {
>>>> + __be32 unused[15];
>>>> + __be16 vlan_etype;
>>>> + __be16 vlan_tci;
>>>> + __be32 data[2];
>>>> +};
>>> [...]
>>>
>>> This is a really nasty way to reclaim space in the union.
>>>
>>> Let's name the union, shrink it and insert the extra fields that way:
>>>
>>> --- a/include/linux/ethtool.h
>>> +++ b/include/linux/ethtool.h
>>> @@ -377,27 +377,43 @@ struct ethtool_usrip4_spec {
>>> __u8 proto;
>>> };
>>>
>>> +union ethtool_flow_union {
>>> + struct ethtool_tcpip4_spec tcp_ip4_spec;
>>> + struct ethtool_tcpip4_spec udp_ip4_spec;
>>> + struct ethtool_tcpip4_spec sctp_ip4_spec;
>>> + struct ethtool_ah_espip4_spec ah_ip4_spec;
>>> + struct ethtool_ah_espip4_spec esp_ip4_spec;
>>> + struct ethtool_usrip4_spec usr_ip4_spec;
>>> + struct ethhdr ether_spec;
>>> + __u8 hdata[52];
>>> +};
>>> +
>>> +struct ethtool_flow_ext {
>>> + __be16 vlan_etype;
>>> + __be16 vlan_tci;
>>> + __be32 data[2];
>>> + __u32 reserved[2];
>>> +};
>>> +
>>
>> Any chance of getting the reserved fields moved to the top of the
>> structure? My only concern is that we might end up with a flow spec
>> larger than 52 bytes at some point and moving the reserved fields to
>> the front might give us a little more wiggle room future
>> compatibility.
> [...]
>
> OK, so how about this:
>
> /**
> * union ethtool_flow_union - flow spec type-specific fields
> * @tcp_ip4_spec: TCP/IPv4 fields to match
> * @udp_ip4_spec: UDP/IPv4 fields to match
> * @sctp_ip4_spec: SCTP/IPv4 fields to match
> * @ah_ip4_spec: AH/IPv4 fields to match
> * @esp_ip4_spec: ESP/IPv4 fields to match
> * @usr_ip4_spec: User-defined IPv4 fields to match
> * @ether_spec: Ethernet fields to match
> *
> * Note: The size of this union may shrink in future to allow for
> * expansion in&struct ethtool_flow_ext.
> */
> union ethtool_flow_union {
> struct ethtool_tcpip4_spec tcp_ip4_spec;
> struct ethtool_tcpip4_spec udp_ip4_spec;
> struct ethtool_tcpip4_spec sctp_ip4_spec;
> struct ethtool_ah_espip4_spec ah_ip4_spec;
> struct ethtool_ah_espip4_spec esp_ip4_spec;
> struct ethtool_usrip4_spec usr_ip4_spec;
> struct ethhdr ether_spec;
> __u8 hdata[60];
> };
>
> /**
> * struct ethtool_flow_ext - flow spec common extension fields
> * @vlan_etype: EtherType for vlan tagged packet to match
> * @vlan_tci: VLAN tag to match
> * @data: Driver-dependent data to match
> *
> * Note: Additional fields may be inserted before @vlan_etype in future,
> * but the offset of the existing fields within the containing structure
> * (&struct ethtool_rx_flow_spec) will be stable.
> */
> struct ethtool_flow_ext {
> __be16 vlan_etype;
> __be16 vlan_tci;
> __be32 data[2];
> };
>
> Please can you check that these definitions won't affect the size of
> struct ethtool_rx_flow_spec on i386 or x86-64?
>
> Ben.
>
I'll try to look into it next week since I am just getting caught up
from being out on vacation.
As I recall when I had made my original changes they didn't have an
effect on the size so this should be fine since all of the fields have a
maximum alignment of 32 bits.
Thanks,
Alex
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2011-03-04 21:01 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-02-25 23:32 [net-next-2.6 PATCH 00/10] Workarounds and fixes for ntuple filters Alexander Duyck
2011-02-25 23:32 ` [net-next-2.6 PATCH 01/10] ethtool: prevent null pointer dereference with NTUPLE set but no set_rx_ntuple Alexander Duyck
2011-02-26 0:21 ` Ben Hutchings
2011-02-26 0:40 ` Alexander Duyck
2011-02-27 0:07 ` David Miller
2011-02-27 2:16 ` Alexander Duyck
2011-02-25 23:32 ` [net-next-2.6 PATCH 02/10] ethtool: add ntuple flow specifier to network flow classifier Alexander Duyck
2011-02-26 1:00 ` Ben Hutchings
2011-02-26 5:30 ` Alexander Duyck
2011-03-02 18:50 ` Ben Hutchings
2011-03-02 19:11 ` Dimitrios Michailidis
2011-03-02 19:27 ` Ben Hutchings
2011-03-02 20:03 ` Dimitrios Michailidis
2011-03-04 19:30 ` Alexander Duyck
2011-03-04 21:00 ` Alexander Duyck
2011-02-27 0:05 ` David Miller
2011-02-25 23:32 ` [net-next-2.6 PATCH 03/10] [RFC] ixgbe: remove ntuple filtering Alexander Duyck
2011-02-25 23:33 ` [net-next-2.6 PATCH 04/10] [RFC] ethtool: remove support for ETHTOOL_GRXNTUPLE Alexander Duyck
2011-02-25 23:33 ` [net-next-2.6 PATCH 05/10] [RFC] ixgbe: add support for different Rx packet buffer sizes Alexander Duyck
2011-02-25 23:33 ` [net-next-2.6 PATCH 06/10] [RFC] ixgbe: update perfect filter framework to support retaining filters Alexander Duyck
2011-02-25 23:33 ` [net-next-2.6 PATCH 07/10] [RFC] ixgbe: add basic support for settting and getting nfc controls Alexander Duyck
2011-02-25 23:33 ` [net-next-2.6 PATCH 08/10] [RFC] ixgbe: add support for displaying ntuple filters via the nfc interface Alexander Duyck
2011-02-25 23:33 ` [net-next-2.6 PATCH 09/10] [RFC] ixgbe: add support for nfc addition and removal of filters Alexander Duyck
2011-02-25 23:33 ` [net-next-2.6 PATCH 10/10] [RFC] ixgbe: Add support for using the same fields as ntuple in nfc Alexander Duyck
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).