qede: Add support for handling IP fragmented packets.
When handling IP fragmented packets with csum in their transport header, the csum isn't changed as part of the fragmentation. As a result, the packet containing the transport headers would have the correct csum of the original packet, but one that mismatches the actual packet that passes on the wire. As a result, on receive path HW would give an indication that the packet has incorrect csum, which would cause qede to discard the incoming packet. Since HW also delivers a notification of IP fragments, change driver behavior to pass such incoming packets to stack and let it make the decision whether it needs to be dropped. Signed-off-by: Manish <manish.chopra@qlogic.com> Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
beb528d01f
commit
c72a6125d0
|
@ -235,6 +235,7 @@ struct qede_rx_queue {
|
||||||
|
|
||||||
u64 rx_hw_errors;
|
u64 rx_hw_errors;
|
||||||
u64 rx_alloc_errors;
|
u64 rx_alloc_errors;
|
||||||
|
u64 rx_ip_frags;
|
||||||
};
|
};
|
||||||
|
|
||||||
union db_prod {
|
union db_prod {
|
||||||
|
|
|
@ -37,6 +37,7 @@ static const struct {
|
||||||
} qede_rqstats_arr[] = {
|
} qede_rqstats_arr[] = {
|
||||||
QEDE_RQSTAT(rx_hw_errors),
|
QEDE_RQSTAT(rx_hw_errors),
|
||||||
QEDE_RQSTAT(rx_alloc_errors),
|
QEDE_RQSTAT(rx_alloc_errors),
|
||||||
|
QEDE_RQSTAT(rx_ip_frags),
|
||||||
};
|
};
|
||||||
|
|
||||||
#define QEDE_NUM_RQSTATS ARRAY_SIZE(qede_rqstats_arr)
|
#define QEDE_NUM_RQSTATS ARRAY_SIZE(qede_rqstats_arr)
|
||||||
|
|
|
@ -1348,6 +1348,20 @@ static u8 qede_check_csum(u16 flag)
|
||||||
return qede_check_tunn_csum(flag);
|
return qede_check_tunn_csum(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool qede_pkt_is_ip_fragmented(struct eth_fast_path_rx_reg_cqe *cqe,
|
||||||
|
u16 flag)
|
||||||
|
{
|
||||||
|
u8 tun_pars_flg = cqe->tunnel_pars_flags.flags;
|
||||||
|
|
||||||
|
if ((tun_pars_flg & (ETH_TUNNEL_PARSING_FLAGS_IPV4_FRAGMENT_MASK <<
|
||||||
|
ETH_TUNNEL_PARSING_FLAGS_IPV4_FRAGMENT_SHIFT)) ||
|
||||||
|
(flag & (PARSING_AND_ERR_FLAGS_IPV4FRAG_MASK <<
|
||||||
|
PARSING_AND_ERR_FLAGS_IPV4FRAG_SHIFT)))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static int qede_rx_int(struct qede_fastpath *fp, int budget)
|
static int qede_rx_int(struct qede_fastpath *fp, int budget)
|
||||||
{
|
{
|
||||||
struct qede_dev *edev = fp->edev;
|
struct qede_dev *edev = fp->edev;
|
||||||
|
@ -1426,6 +1440,12 @@ static int qede_rx_int(struct qede_fastpath *fp, int budget)
|
||||||
|
|
||||||
csum_flag = qede_check_csum(parse_flag);
|
csum_flag = qede_check_csum(parse_flag);
|
||||||
if (unlikely(csum_flag == QEDE_CSUM_ERROR)) {
|
if (unlikely(csum_flag == QEDE_CSUM_ERROR)) {
|
||||||
|
if (qede_pkt_is_ip_fragmented(&cqe->fast_path_regular,
|
||||||
|
parse_flag)) {
|
||||||
|
rxq->rx_ip_frags++;
|
||||||
|
goto alloc_skb;
|
||||||
|
}
|
||||||
|
|
||||||
DP_NOTICE(edev,
|
DP_NOTICE(edev,
|
||||||
"CQE in CONS = %u has error, flags = %x, dropping incoming packet\n",
|
"CQE in CONS = %u has error, flags = %x, dropping incoming packet\n",
|
||||||
sw_comp_cons, parse_flag);
|
sw_comp_cons, parse_flag);
|
||||||
|
@ -1434,6 +1454,7 @@ static int qede_rx_int(struct qede_fastpath *fp, int budget)
|
||||||
goto next_cqe;
|
goto next_cqe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alloc_skb:
|
||||||
skb = netdev_alloc_skb(edev->ndev, QEDE_RX_HDR_SIZE);
|
skb = netdev_alloc_skb(edev->ndev, QEDE_RX_HDR_SIZE);
|
||||||
if (unlikely(!skb)) {
|
if (unlikely(!skb)) {
|
||||||
DP_NOTICE(edev,
|
DP_NOTICE(edev,
|
||||||
|
|
Loading…
Reference in New Issue