net: aquantia: invalid checksumm offload implementation
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>
This commit is contained in:
parent
bfaa9f8553
commit
ad703c2b91
|
@ -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,
|
||||
|
@ -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 :
|
||||
|
|
|
@ -660,9 +660,9 @@ 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;
|
||||
|
@ -670,35 +670,35 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self,
|
|||
|
||||
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) {
|
||||
|
|
Loading…
Reference in New Issue