Skip to content

Commit

Permalink
net: aquantia: invalid checksumm offload implementation
Browse files Browse the repository at this point in the history
Packets with marked invalid IP/UDP/TCP checksums were considered as good
by the driver. The error was in a logic, processing offload bits in
RX descriptor.

Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Dmitry Bogdanov authored and David S. Miller committed Nov 9, 2018
1 parent bfaa9f8 commit ad703c2
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 30 deletions.
35 changes: 23 additions & 12 deletions drivers/net/ethernet/aquantia/atlantic/aq_ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,27 @@ bool aq_ring_tx_clean(struct aq_ring_s *self)
return !!budget;
}

static void aq_rx_checksum(struct aq_ring_s *self,
struct aq_ring_buff_s *buff,
struct sk_buff *skb)
{
if (!(self->aq_nic->ndev->features & NETIF_F_RXCSUM))
return;

if (unlikely(buff->is_cso_err)) {
++self->stats.rx.errors;
skb->ip_summed = CHECKSUM_NONE;
return;
}
if (buff->is_ip_cso) {
__skb_incr_checksum_unnecessary(skb);
if (buff->is_udp_cso || buff->is_tcp_cso)
__skb_incr_checksum_unnecessary(skb);
} else {
skb->ip_summed = CHECKSUM_NONE;
}
}

#define AQ_SKB_ALIGN SKB_DATA_ALIGN(sizeof(struct skb_shared_info))
int aq_ring_rx_clean(struct aq_ring_s *self,
struct napi_struct *napi,
Expand Down Expand Up @@ -267,18 +288,8 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
}

skb->protocol = eth_type_trans(skb, ndev);
if (unlikely(buff->is_cso_err)) {
++self->stats.rx.errors;
skb->ip_summed = CHECKSUM_NONE;
} else {
if (buff->is_ip_cso) {
__skb_incr_checksum_unnecessary(skb);
if (buff->is_udp_cso || buff->is_tcp_cso)
__skb_incr_checksum_unnecessary(skb);
} else {
skb->ip_summed = CHECKSUM_NONE;
}
}

aq_rx_checksum(self, buff, skb);

skb_set_hash(skb, buff->rss_hash,
buff->is_hash_l4 ? PKT_HASH_TYPE_L4 :
Expand Down
36 changes: 18 additions & 18 deletions drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
Original file line number Diff line number Diff line change
Expand Up @@ -660,45 +660,45 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self,
struct hw_atl_rxd_wb_s *rxd_wb = (struct hw_atl_rxd_wb_s *)
&ring->dx_ring[ring->hw_head * HW_ATL_B0_RXD_SIZE];

unsigned int is_err = 1U;
unsigned int is_rx_check_sum_enabled = 0U;
unsigned int pkt_type = 0U;
u8 rx_stat = 0U;

if (!(rxd_wb->status & 0x1U)) { /* RxD is not done */
break;
}

buff = &ring->buff_ring[ring->hw_head];

is_err = (0x0000003CU & rxd_wb->status);
rx_stat = (0x0000003CU & rxd_wb->status) >> 2;

is_rx_check_sum_enabled = (rxd_wb->type) & (0x3U << 19);
is_err &= ~0x20U; /* exclude validity bit */

pkt_type = 0xFFU & (rxd_wb->type >> 4);

if (is_rx_check_sum_enabled) {
if (0x0U == (pkt_type & 0x3U))
buff->is_ip_cso = (is_err & 0x08U) ? 0U : 1U;
if (is_rx_check_sum_enabled & BIT(0) &&
(0x0U == (pkt_type & 0x3U)))
buff->is_ip_cso = (rx_stat & BIT(1)) ? 0U : 1U;

if (is_rx_check_sum_enabled & BIT(1)) {
if (0x4U == (pkt_type & 0x1CU))
buff->is_udp_cso = buff->is_cso_err ? 0U : 1U;
buff->is_udp_cso = (rx_stat & BIT(2)) ? 0U :
!!(rx_stat & BIT(3));
else if (0x0U == (pkt_type & 0x1CU))
buff->is_tcp_cso = buff->is_cso_err ? 0U : 1U;

/* Checksum offload workaround for small packets */
if (rxd_wb->pkt_len <= 60) {
buff->is_ip_cso = 0U;
buff->is_cso_err = 0U;
}
buff->is_tcp_cso = (rx_stat & BIT(2)) ? 0U :
!!(rx_stat & BIT(3));
}
buff->is_cso_err = !!(rx_stat & 0x6);
/* Checksum offload workaround for small packets */
if (unlikely(rxd_wb->pkt_len <= 60)) {
buff->is_ip_cso = 0U;
buff->is_cso_err = 0U;
}

is_err &= ~0x18U;

dma_unmap_page(ndev, buff->pa, buff->len, DMA_FROM_DEVICE);

if (is_err || rxd_wb->type & 0x1000U) {
/* status error or DMA error */
if ((rx_stat & BIT(0)) || rxd_wb->type & 0x1000U) {
/* MAC error or DMA error */
buff->is_error = 1U;
} else {
if (self->aq_nic_cfg->is_rss) {
Expand Down

0 comments on commit ad703c2

Please sign in to comment.