* [PATCH V2 net-next 0/2] Add CHECKSUM_COMPLETE support
@ 2014-11-06 16:28 Or Gerlitz
2014-11-06 16:28 ` [PATCH V2 net-next 1/2] net/mlx4_en: Extend usage of napi_gro_frags Or Gerlitz
2014-11-06 16:28 ` [PATCH V2 net-next 2/2] net/mlx4_en: Extend checksum offloading by CHECKSUM COMPLETE Or Gerlitz
0 siblings, 2 replies; 6+ messages in thread
From: Or Gerlitz @ 2014-11-06 16:28 UTC (permalink / raw)
To: David S. Miller
Cc: netdev, Matan Barak, Amir Vadai, Saeed Mahameed, Shani Michaeli,
Ido Shamay, Or Gerlitz
Hi Dave,
These patches from Shani, Matan and myself add support for
CHECKSUM_COMPLETE reporting on non TCP/UDP packets such as
GRE and ICMP. I'd like to deeply thank Jerry Chu for his
innovation and support in that effort.
Based on the feedback from Eric and Ido Shamay, in V2 we dropped
the patch which removed the calls to napi_gro_frags() and added
a patch which makes the RX code to go through that path
regardless of the checksum status.
Or.
changes from V0/V1:
- added a patch to extend usage napi_gro_frags()
- applied feedback from David Laight to optimally use checksum helpers
Shani Michaeli (2):
net/mlx4_en: Extend usage of napi_gro_frags
net/mlx4_en: Extend checksum offloading by CHECKSUM COMPLETE
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 2 +-
drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 5 +
drivers/net/ethernet/mellanox/mlx4/en_port.c | 2 +
drivers/net/ethernet/mellanox/mlx4/en_rx.c | 229 +++++++++++++++++------
drivers/net/ethernet/mellanox/mlx4/main.c | 9 +
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 5 +-
include/linux/mlx4/device.h | 1 +
7 files changed, 193 insertions(+), 60 deletions(-)
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH V2 net-next 1/2] net/mlx4_en: Extend usage of napi_gro_frags
2014-11-06 16:28 [PATCH V2 net-next 0/2] Add CHECKSUM_COMPLETE support Or Gerlitz
@ 2014-11-06 16:28 ` Or Gerlitz
2014-11-06 16:28 ` [PATCH V2 net-next 2/2] net/mlx4_en: Extend checksum offloading by CHECKSUM COMPLETE Or Gerlitz
1 sibling, 0 replies; 6+ messages in thread
From: Or Gerlitz @ 2014-11-06 16:28 UTC (permalink / raw)
To: David S. Miller
Cc: netdev, Matan Barak, Amir Vadai, Saeed Mahameed, Shani Michaeli,
Ido Shamay, Or Gerlitz
From: Shani Michaeli <shanim@mellanox.com>
We can call napi_gro_frags for all the received traffic regardless
of the checksum status. Specifically, received packets whose status
is CHECKSUM_NONE (and soon to be added CHECKSUM_COMPLETE)
are eligible for napi_gro_frags as well.
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Shani Michaeli <shanim@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx4/en_rx.c | 108 ++++++++++++++--------------
1 files changed, 54 insertions(+), 54 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index b173a0c..c83127e 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -747,60 +747,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
(cqe->checksum == cpu_to_be16(0xffff))) {
ring->csum_ok++;
- /* This packet is eligible for GRO if it is:
- * - DIX Ethernet (type interpretation)
- * - TCP/IP (v4)
- * - without IP options
- * - not an IP fragment
- * - no LLS polling in progress
- */
- if (!mlx4_en_cq_busy_polling(cq) &&
- (dev->features & NETIF_F_GRO)) {
- struct sk_buff *gro_skb = napi_get_frags(&cq->napi);
- if (!gro_skb)
- goto next;
-
- nr = mlx4_en_complete_rx_desc(priv,
- rx_desc, frags, gro_skb,
- length);
- if (!nr)
- goto next;
-
- skb_shinfo(gro_skb)->nr_frags = nr;
- gro_skb->len = length;
- gro_skb->data_len = length;
- gro_skb->ip_summed = CHECKSUM_UNNECESSARY;
-
- if (l2_tunnel)
- gro_skb->csum_level = 1;
- if ((cqe->vlan_my_qpn &
- cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)) &&
- (dev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
- u16 vid = be16_to_cpu(cqe->sl_vid);
-
- __vlan_hwaccel_put_tag(gro_skb, htons(ETH_P_8021Q), vid);
- }
-
- if (dev->features & NETIF_F_RXHASH)
- skb_set_hash(gro_skb,
- be32_to_cpu(cqe->immed_rss_invalid),
- PKT_HASH_TYPE_L3);
-
- skb_record_rx_queue(gro_skb, cq->ring);
- skb_mark_napi_id(gro_skb, &cq->napi);
-
- if (ring->hwtstamp_rx_filter == HWTSTAMP_FILTER_ALL) {
- timestamp = mlx4_en_get_cqe_ts(cqe);
- mlx4_en_fill_hwtstamps(mdev,
- skb_hwtstamps(gro_skb),
- timestamp);
- }
-
- napi_gro_frags(&cq->napi);
- goto next;
- }
-
- /* GRO not possible, complete processing here */
ip_summed = CHECKSUM_UNNECESSARY;
} else {
ip_summed = CHECKSUM_NONE;
@@ -811,6 +757,60 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
ring->csum_none++;
}
+ /* This packet is eligible for GRO if it is:
+ * - DIX Ethernet (type interpretation)
+ * - TCP/IP (v4)
+ * - without IP options
+ * - not an IP fragment
+ * - no LLS polling in progress
+ */
+ if (!mlx4_en_cq_busy_polling(cq) &&
+ (dev->features & NETIF_F_GRO)) {
+ struct sk_buff *gro_skb = napi_get_frags(&cq->napi);
+ if (!gro_skb)
+ goto next;
+
+ nr = mlx4_en_complete_rx_desc(priv,
+ rx_desc, frags, gro_skb,
+ length);
+ if (!nr)
+ goto next;
+
+ skb_shinfo(gro_skb)->nr_frags = nr;
+ gro_skb->len = length;
+ gro_skb->data_len = length;
+ gro_skb->ip_summed = ip_summed;
+
+ if (l2_tunnel && ip_summed == CHECKSUM_UNNECESSARY)
+ gro_skb->encapsulation = 1;
+ if ((cqe->vlan_my_qpn &
+ cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)) &&
+ (dev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
+ u16 vid = be16_to_cpu(cqe->sl_vid);
+
+ __vlan_hwaccel_put_tag(gro_skb, htons(ETH_P_8021Q), vid);
+ }
+
+ if (dev->features & NETIF_F_RXHASH)
+ skb_set_hash(gro_skb,
+ be32_to_cpu(cqe->immed_rss_invalid),
+ PKT_HASH_TYPE_L3);
+
+ skb_record_rx_queue(gro_skb, cq->ring);
+ skb_mark_napi_id(gro_skb, &cq->napi);
+
+ if (ring->hwtstamp_rx_filter == HWTSTAMP_FILTER_ALL) {
+ timestamp = mlx4_en_get_cqe_ts(cqe);
+ mlx4_en_fill_hwtstamps(mdev,
+ skb_hwtstamps(gro_skb),
+ timestamp);
+ }
+
+ napi_gro_frags(&cq->napi);
+ goto next;
+ }
+
+ /* GRO not possible, complete processing here */
skb = mlx4_en_rx_skb(priv, rx_desc, frags, length);
if (!skb) {
priv->stats.rx_dropped++;
--
1.7.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH V2 net-next 2/2] net/mlx4_en: Extend checksum offloading by CHECKSUM COMPLETE
2014-11-06 16:28 [PATCH V2 net-next 0/2] Add CHECKSUM_COMPLETE support Or Gerlitz
2014-11-06 16:28 ` [PATCH V2 net-next 1/2] net/mlx4_en: Extend usage of napi_gro_frags Or Gerlitz
@ 2014-11-06 16:28 ` Or Gerlitz
2014-11-07 8:40 ` Ido Shamay
2014-11-09 8:14 ` Amir Vadai
1 sibling, 2 replies; 6+ messages in thread
From: Or Gerlitz @ 2014-11-06 16:28 UTC (permalink / raw)
To: David S. Miller
Cc: netdev, Matan Barak, Amir Vadai, Saeed Mahameed, Shani Michaeli,
Ido Shamay, Jerry Chu, Or Gerlitz
From: Shani Michaeli <shanim@mellanox.com>
When processing received traffic, pass CHECKSUM_COMPLETE status to the
stack, with calculated checksum for non TCP/UDP packets (such
as GRE or ICMP).
Although the stack expects checksum which doesn't include the pseudo
header, the HW adds it. To address that, we are subtracting the pseudo
header checksum from the checksum value provided by the HW.
In the IPv6 case, we also compute/add the IP header checksum which
is not added by the HW for such packets.
Cc: Jerry Chu <hkchu@google.com>
Signed-off-by: Shani Michaeli <shanim@mellanox.com>
Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 2 +-
drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 5 +
drivers/net/ethernet/mellanox/mlx4/en_port.c | 2 +
drivers/net/ethernet/mellanox/mlx4/en_rx.c | 127 +++++++++++++++++++++--
drivers/net/ethernet/mellanox/mlx4/main.c | 9 ++
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 5 +-
include/linux/mlx4/device.h | 1 +
7 files changed, 142 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index 8ea4d5b..6c64323 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -115,7 +115,7 @@ static const char main_strings[][ETH_GSTRING_LEN] = {
"tso_packets",
"xmit_more",
"queue_stopped", "wake_queue", "tx_timeout", "rx_alloc_failed",
- "rx_csum_good", "rx_csum_none", "tx_chksum_offload",
+ "rx_csum_good", "rx_csum_none", "rx_csum_complete", "tx_chksum_offload",
/* packet statistics */
"broadcast", "rx_prio_0", "rx_prio_1", "rx_prio_2", "rx_prio_3",
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 0efbae9..d1eb25d 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -1893,6 +1893,7 @@ static void mlx4_en_clear_stats(struct net_device *dev)
priv->rx_ring[i]->packets = 0;
priv->rx_ring[i]->csum_ok = 0;
priv->rx_ring[i]->csum_none = 0;
+ priv->rx_ring[i]->csum_complete = 0;
}
}
@@ -2503,6 +2504,10 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
/* Query for default mac and max mtu */
priv->max_mtu = mdev->dev->caps.eth_mtu_cap[priv->port];
+ if (mdev->dev->caps.rx_checksum_flags_port[priv->port] &
+ MLX4_RX_CSUM_MODE_VAL_NON_TCP_UDP)
+ priv->flags |= MLX4_EN_FLAG_RX_CSUM_NON_TCP_UDP;
+
/* Set default MAC */
dev->addr_len = ETH_ALEN;
mlx4_en_u64_to_mac(dev->dev_addr, mdev->dev->caps.def_mac[priv->port]);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_port.c b/drivers/net/ethernet/mellanox/mlx4/en_port.c
index 134b12e..6cb8007 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_port.c
@@ -155,11 +155,13 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
stats->rx_bytes = 0;
priv->port_stats.rx_chksum_good = 0;
priv->port_stats.rx_chksum_none = 0;
+ priv->port_stats.rx_chksum_complete = 0;
for (i = 0; i < priv->rx_ring_num; i++) {
stats->rx_packets += priv->rx_ring[i]->packets;
stats->rx_bytes += priv->rx_ring[i]->bytes;
priv->port_stats.rx_chksum_good += priv->rx_ring[i]->csum_ok;
priv->port_stats.rx_chksum_none += priv->rx_ring[i]->csum_none;
+ priv->port_stats.rx_chksum_complete += priv->rx_ring[i]->csum_complete;
}
stats->tx_packets = 0;
stats->tx_bytes = 0;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index c83127e..25065c2 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -42,6 +42,10 @@
#include <linux/vmalloc.h>
#include <linux/irq.h>
+#if IS_ENABLED(CONFIG_IPV6)
+#include <net/ip6_checksum.h>
+#endif
+
#include "mlx4_en.h"
static int mlx4_alloc_pages(struct mlx4_en_priv *priv,
@@ -643,6 +647,86 @@ static void mlx4_en_refill_rx_buffers(struct mlx4_en_priv *priv,
}
}
+/* When hardware doesn't strip the vlan, we need to calculate the checksum
+ * over it and add it to the hardware's checksum calculation
+ */
+static inline __wsum get_fixed_vlan_csum(__wsum hw_checksum,
+ struct vlan_hdr *vlanh)
+{
+ return csum_add(hw_checksum, *(__wsum *)vlanh);
+}
+
+/* Although the stack expects checksum which doesn't include the pseudo
+ * header, the HW adds it. To address that, we are subtracting the pseudo
+ * header checksum from the checksum value provided by the HW.
+ */
+static void get_fixed_ipv4_csum(__wsum hw_checksum, struct sk_buff *skb,
+ struct iphdr *iph)
+{
+ __u16 length_for_csum = 0;
+ __wsum csum_pseudo_header = 0;
+
+ length_for_csum = (be16_to_cpu(iph->tot_len) - (iph->ihl << 2));
+ csum_pseudo_header = csum_tcpudp_nofold(iph->saddr, iph->daddr,
+ length_for_csum, iph->protocol, 0);
+ skb->csum = csum_sub(hw_checksum, csum_pseudo_header);
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+/* In IPv6 packets, besides subtracting the pseudo header checksum,
+ * we also compute/add the IP header checksum which
+ * is not added by the HW.
+ */
+static int get_fixed_ipv6_csum(__wsum hw_checksum, struct sk_buff *skb,
+ struct ipv6hdr *ipv6h)
+{
+ __wsum csum_pseudo_hdr = 0;
+
+ if (ipv6h->nexthdr == IPPROTO_FRAGMENT || ipv6h->nexthdr == IPPROTO_HOPOPTS)
+ return -1;
+ hw_checksum = csum_add(hw_checksum, (__force __wsum)(ipv6h->nexthdr << 8));
+
+ csum_pseudo_hdr = csum_partial(&ipv6h->saddr,
+ sizeof(ipv6h->saddr) + sizeof(ipv6h->daddr), 0);
+ csum_pseudo_hdr = csum_add(csum_pseudo_hdr, (__force __wsum)ipv6h->payload_len);
+ csum_pseudo_hdr = csum_add(csum_pseudo_hdr, (__force __wsum)ntohs(ipv6h->nexthdr));
+
+ skb->csum = csum_sub(hw_checksum, csum_pseudo_hdr);
+ skb->csum = csum_add(skb->csum, csum_partial(ipv6h, sizeof(struct ipv6hdr), 0));
+ return 0;
+}
+#endif
+static int check_csum(struct mlx4_cqe *cqe, struct sk_buff *skb, void *va,
+ int hwtstamp_rx_filter)
+{
+ __wsum hw_checksum = 0;
+
+ void *hdr = (u8 *)va + sizeof(struct ethhdr);
+
+ hw_checksum = csum_unfold((__force __sum16)cqe->checksum);
+
+ if (((struct ethhdr *)va)->h_proto == htons(ETH_P_8021Q) &&
+ hwtstamp_rx_filter != HWTSTAMP_FILTER_NONE) {
+ /* next protocol non IPv4 or IPv6 */
+ if (((struct vlan_hdr *)hdr)->h_vlan_encapsulated_proto
+ != htons(ETH_P_IP) &&
+ ((struct vlan_hdr *)hdr)->h_vlan_encapsulated_proto
+ != htons(ETH_P_IPV6))
+ return -1;
+ hw_checksum = get_fixed_vlan_csum(hw_checksum, hdr);
+ hdr += sizeof(struct vlan_hdr);
+ }
+
+ if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPV4))
+ get_fixed_ipv4_csum(hw_checksum, skb, hdr);
+#if IS_ENABLED(CONFIG_IPV6)
+ else if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPV6))
+ if (get_fixed_ipv6_csum(hw_checksum, skb, hdr))
+ return -1;
+#endif
+ return 0;
+}
+
int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
@@ -660,6 +744,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
int factor = priv->cqe_factor;
u64 timestamp;
bool l2_tunnel;
+ void *va = 0;
if (!priv->port_up)
return 0;
@@ -702,8 +787,8 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
* and not performing the selftest or flb disabled
*/
if (priv->flags & MLX4_EN_FLAG_RX_FILTER_NEEDED) {
- struct ethhdr *ethh;
dma_addr_t dma;
+ struct ethhdr *ethh;
/* Get pointer to first fragment since we haven't
* skb yet and cast it to ethhdr struct
*/
@@ -744,13 +829,26 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
(cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_L2_TUNNEL));
if (likely(dev->features & NETIF_F_RXCSUM)) {
- if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
- (cqe->checksum == cpu_to_be16(0xffff))) {
- ring->csum_ok++;
- ip_summed = CHECKSUM_UNNECESSARY;
+ if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_TCP |
+ MLX4_CQE_STATUS_UDP)) {
+ if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
+ cqe->checksum == cpu_to_be16(0xffff)) {
+ ip_summed = CHECKSUM_UNNECESSARY;
+ ring->csum_ok++;
+ } else {
+ ip_summed = CHECKSUM_NONE;
+ ring->csum_none++;
+ }
} else {
- ip_summed = CHECKSUM_NONE;
- ring->csum_none++;
+ if (priv->flags & MLX4_EN_FLAG_RX_CSUM_NON_TCP_UDP &&
+ (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPV4 |
+ MLX4_CQE_STATUS_IPV6))) {
+ ip_summed = CHECKSUM_COMPLETE;
+ ring->csum_complete++;
+ } else {
+ ip_summed = CHECKSUM_NONE;
+ ring->csum_none++;
+ }
}
} else {
ip_summed = CHECKSUM_NONE;
@@ -776,6 +874,14 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
if (!nr)
goto next;
+ if (ip_summed == CHECKSUM_COMPLETE) {
+ va = skb_frag_address(skb_shinfo(gro_skb)->frags);
+ if (check_csum(cqe, gro_skb, va, ring->hwtstamp_rx_filter)) {
+ ip_summed = CHECKSUM_NONE;
+ ring->csum_none++;
+ }
+ }
+
skb_shinfo(gro_skb)->nr_frags = nr;
gro_skb->len = length;
gro_skb->data_len = length;
@@ -822,6 +928,13 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
goto next;
}
+ if (ip_summed == CHECKSUM_COMPLETE) {
+ if (check_csum(cqe, skb, skb->data, ring->hwtstamp_rx_filter)) {
+ ip_summed = CHECKSUM_NONE;
+ ring->csum_none++;
+ }
+ }
+
skb->ip_summed = ip_summed;
skb->protocol = eth_type_trans(skb, dev);
skb_record_rx_queue(skb, cq->ring);
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 9f82196..2f6ba42 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -1629,6 +1629,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
struct mlx4_init_hca_param init_hca;
u64 icm_size;
int err;
+ struct mlx4_config_dev_params params;
if (!mlx4_is_slave(dev)) {
err = mlx4_QUERY_FW(dev);
@@ -1762,6 +1763,14 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
goto unmap_bf;
}
+ /* Query CONFIG_DEV parameters */
+ err = mlx4_config_dev_retrieval(dev, ¶ms);
+ if (err && err != -ENOTSUPP) {
+ mlx4_err(dev, "Failed to query CONFIG_DEV parameters\n");
+ } else if (!err) {
+ dev->caps.rx_checksum_flags_port[1] = params.rx_csum_flags_port_1;
+ dev->caps.rx_checksum_flags_port[2] = params.rx_csum_flags_port_2;
+ }
priv->eq_table.inta_pin = adapter.inta_pin;
memcpy(dev->board_id, adapter.board_id, sizeof dev->board_id);
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index ef83d12..de45674 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -326,6 +326,7 @@ struct mlx4_en_rx_ring {
#endif
unsigned long csum_ok;
unsigned long csum_none;
+ unsigned long csum_complete;
int hwtstamp_rx_filter;
cpumask_var_t affinity_mask;
};
@@ -449,6 +450,7 @@ struct mlx4_en_port_stats {
unsigned long rx_alloc_failed;
unsigned long rx_chksum_good;
unsigned long rx_chksum_none;
+ unsigned long rx_chksum_complete;
unsigned long tx_chksum_offload;
#define NUM_PORT_STATS 9
};
@@ -507,7 +509,8 @@ enum {
MLX4_EN_FLAG_ENABLE_HW_LOOPBACK = (1 << 2),
/* whether we need to drop packets that hardware loopback-ed */
MLX4_EN_FLAG_RX_FILTER_NEEDED = (1 << 3),
- MLX4_EN_FLAG_FORCE_PROMISC = (1 << 4)
+ MLX4_EN_FLAG_FORCE_PROMISC = (1 << 4),
+ MLX4_EN_FLAG_RX_CSUM_NON_TCP_UDP = (1 << 5),
};
#define MLX4_EN_MAC_HASH_SIZE (1 << BITS_PER_BYTE)
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 5cc5eac..3d9bff0 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -497,6 +497,7 @@ struct mlx4_caps {
u16 hca_core_clock;
u64 phys_port_id[MLX4_MAX_PORTS + 1];
int tunnel_offload_mode;
+ u8 rx_checksum_flags_port[MLX4_MAX_PORTS + 1];
};
struct mlx4_buf_list {
--
1.7.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH V2 net-next 2/2] net/mlx4_en: Extend checksum offloading by CHECKSUM COMPLETE
2014-11-06 16:28 ` [PATCH V2 net-next 2/2] net/mlx4_en: Extend checksum offloading by CHECKSUM COMPLETE Or Gerlitz
@ 2014-11-07 8:40 ` Ido Shamay
2014-11-09 8:24 ` Or Gerlitz
2014-11-09 8:14 ` Amir Vadai
1 sibling, 1 reply; 6+ messages in thread
From: Ido Shamay @ 2014-11-07 8:40 UTC (permalink / raw)
To: Or Gerlitz, David S. Miller
Cc: netdev, Matan Barak, Amir Vadai, Saeed Mahameed, Shani Michaeli,
Ido Shamay, Jerry Chu
On 11/6/2014 6:28 PM, Or Gerlitz wrote:
> if (likely(dev->features & NETIF_F_RXCSUM)) {
> - if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
> - (cqe->checksum == cpu_to_be16(0xffff))) {
> - ring->csum_ok++;
> - ip_summed = CHECKSUM_UNNECESSARY;
> + if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_TCP |
> + MLX4_CQE_STATUS_UDP)) {
> + if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
> + cqe->checksum == cpu_to_be16(0xffff)) {
> + ip_summed = CHECKSUM_UNNECESSARY;
> + ring->csum_ok++;
> + } else {
> + ip_summed = CHECKSUM_NONE;
> + ring->csum_none++;
> + }
> } else {
> - ip_summed = CHECKSUM_NONE;
> - ring->csum_none++;
> + if (priv->flags & MLX4_EN_FLAG_RX_CSUM_NON_TCP_UDP &&
> + (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPV4 |
> + MLX4_CQE_STATUS_IPV6))) {
> + ip_summed = CHECKSUM_COMPLETE;
> + ring->csum_complete++;
> + } else {
> + ip_summed = CHECKSUM_NONE;
> + ring->csum_none++;
> + }
> }
> } else {
> ip_summed = CHECKSUM_NONE;
> @@ -776,6 +874,14 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
> if (!nr)
> goto next;
>
> + if (ip_summed == CHECKSUM_COMPLETE) {
> + va = skb_frag_address(skb_shinfo(gro_skb)->frags);
> + if (check_csum(cqe, gro_skb, va, ring->hwtstamp_rx_filter)) {
> + ip_summed = CHECKSUM_NONE;
> + ring->csum_none++;
When check_csum returns non zero value, then ring->csum_complete counter
was already incremented, and now we are incrementing ring->csum_none
(for the same packet), so need to --ring->csum_complete.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH V2 net-next 2/2] net/mlx4_en: Extend checksum offloading by CHECKSUM COMPLETE
2014-11-06 16:28 ` [PATCH V2 net-next 2/2] net/mlx4_en: Extend checksum offloading by CHECKSUM COMPLETE Or Gerlitz
2014-11-07 8:40 ` Ido Shamay
@ 2014-11-09 8:14 ` Amir Vadai
1 sibling, 0 replies; 6+ messages in thread
From: Amir Vadai @ 2014-11-09 8:14 UTC (permalink / raw)
To: Or Gerlitz, David S. Miller
Cc: netdev, Matan Barak, Saeed Mahameed, Shani Michaeli, Ido Shamay,
Jerry Chu
On 11/6/2014 6:28 PM, Or Gerlitz wrote:
> From: Shani Michaeli <shanim@mellanox.com>
>
> When processing received traffic, pass CHECKSUM_COMPLETE status to the
> stack, with calculated checksum for non TCP/UDP packets (such
> as GRE or ICMP).
>
> Although the stack expects checksum which doesn't include the pseudo
> header, the HW adds it. To address that, we are subtracting the pseudo
> header checksum from the checksum value provided by the HW.
>
> In the IPv6 case, we also compute/add the IP header checksum which
> is not added by the HW for such packets.
>
> Cc: Jerry Chu <hkchu@google.com>
> Signed-off-by: Shani Michaeli <shanim@mellanox.com>
> Signed-off-by: Matan Barak <matanb@mellanox.com>
> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
> ---
> drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 2 +-
> drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 5 +
> drivers/net/ethernet/mellanox/mlx4/en_port.c | 2 +
> drivers/net/ethernet/mellanox/mlx4/en_rx.c | 127 +++++++++++++++++++++--
> drivers/net/ethernet/mellanox/mlx4/main.c | 9 ++
> drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 5 +-
> include/linux/mlx4/device.h | 1 +
> 7 files changed, 142 insertions(+), 9 deletions(-)
>
[...]
> @@ -702,8 +787,8 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
> * and not performing the selftest or flb disabled
> */
> if (priv->flags & MLX4_EN_FLAG_RX_FILTER_NEEDED) {
> - struct ethhdr *ethh;
> dma_addr_t dma;
> + struct ethhdr *ethh;
> /* Get pointer to first fragment since we haven't
> * skb yet and cast it to ethhdr struct
> */
This hunk is not needed
> @@ -744,13 +829,26 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
> (cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_L2_TUNNEL));
[...]
Amir
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH V2 net-next 2/2] net/mlx4_en: Extend checksum offloading by CHECKSUM COMPLETE
2014-11-07 8:40 ` Ido Shamay
@ 2014-11-09 8:24 ` Or Gerlitz
0 siblings, 0 replies; 6+ messages in thread
From: Or Gerlitz @ 2014-11-09 8:24 UTC (permalink / raw)
To: Amir Vadai, Ido Shamay
Cc: David S. Miller, Linux Netdev List, Matan Barak, Saeed Mahameed,
Shani Michaeli, Jerry Chu
On Fri, Nov 7, 2014 at 10:40 AM, Ido Shamay <idos@dev.mellanox.co.il> wrote:
> On 11/6/2014 6:28 PM, Or Gerlitz wrote:
>>
>> if (likely(dev->features & NETIF_F_RXCSUM)) {
>> - if ((cqe->status &
>> cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
>> - (cqe->checksum == cpu_to_be16(0xffff))) {
>> - ring->csum_ok++;
>> - ip_summed = CHECKSUM_UNNECESSARY;
>> + if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_TCP
>> |
>> +
>> MLX4_CQE_STATUS_UDP)) {
>> + if ((cqe->status &
>> cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
>> + cqe->checksum == cpu_to_be16(0xffff))
>> {
>> + ip_summed = CHECKSUM_UNNECESSARY;
>> + ring->csum_ok++;
>> + } else {
>> + ip_summed = CHECKSUM_NONE;
>> + ring->csum_none++;
>> + }
>> } else {
>> - ip_summed = CHECKSUM_NONE;
>> - ring->csum_none++;
>> + if (priv->flags &
>> MLX4_EN_FLAG_RX_CSUM_NON_TCP_UDP &&
>> + (cqe->status &
>> cpu_to_be16(MLX4_CQE_STATUS_IPV4 |
>> +
>> MLX4_CQE_STATUS_IPV6))) {
>> + ip_summed = CHECKSUM_COMPLETE;
>> + ring->csum_complete++;
>> + } else {
>> + ip_summed = CHECKSUM_NONE;
>> + ring->csum_none++;
>> + }
>> }
>> } else {
>> ip_summed = CHECKSUM_NONE;
>> @@ -776,6 +874,14 @@ int mlx4_en_process_rx_cq(struct net_device *dev,
>> struct mlx4_en_cq *cq, int bud
>> if (!nr)
>> goto next;
>>
>> + if (ip_summed == CHECKSUM_COMPLETE) {
>> + va =
>> skb_frag_address(skb_shinfo(gro_skb)->frags);
>> + if (check_csum(cqe, gro_skb, va,
>> ring->hwtstamp_rx_filter)) {
>> + ip_summed = CHECKSUM_NONE;
>> + ring->csum_none++;
>
>
> When check_csum returns non zero value, then ring->csum_complete counter was
> already incremented, and now we are incrementing ring->csum_none (for the
> same packet), so need to --ring->csum_complete.
Thanks Ido, I'll fix that.
Amir, I saw the little noise you just reported on too but didn't want
to re-spin V1 just for that, thanks for catching this up.
>
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2014-11-09 8:24 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-06 16:28 [PATCH V2 net-next 0/2] Add CHECKSUM_COMPLETE support Or Gerlitz
2014-11-06 16:28 ` [PATCH V2 net-next 1/2] net/mlx4_en: Extend usage of napi_gro_frags Or Gerlitz
2014-11-06 16:28 ` [PATCH V2 net-next 2/2] net/mlx4_en: Extend checksum offloading by CHECKSUM COMPLETE Or Gerlitz
2014-11-07 8:40 ` Ido Shamay
2014-11-09 8:24 ` Or Gerlitz
2014-11-09 8:14 ` Amir Vadai
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.