[dpdk-users] .hw_strip_crc weird behavior with small UDP packets
Julien Castets
castets.j at gmail.com
Mon Feb 1 17:51:49 CET 2016
Hi,
I dump the packets received with rte_pktmbuf_dump(stderr, pkt,
pkt->data_len) and I have a strange behavior related to CRC stripping
with small UDP packets. By "small", I mean below the minimal ethernet
payload size, ie. 46 bytes.
* case 1: when my device is configured with hw_strip_crc=1 and the UDP
data is "aaa\n" (4 bytes), my function outputs:
dump mbuf at 0x0x7fe93bdc47c0, phys=2dbc4840, buf_len=1920
pkt_len=60, ol_flags=2, nb_segs=1, in_port=1
segment at 0x0x7fe93bdc47c0, data=0x0x7fe93bdc48c0, data_len=60
Dump data at [0x7fe93bdc48c0], len=60
00000000: 38 EA A7 92 70 28 58 97 BD 4F 6F C7 08 00 45 00 | 8...p(X..Oo...E.
00000010: 00 20 26 D5 00 00 39 11 3B FD D5 24 07 1F A3 AC | . &...9.;..$....
00000020: 9F 0B EA 5D 10 92 00 0C 23 7F 61 61 61 0A 00 00 | ...]....#.aaa...
00000030: 00 00 00 00 00 00 00 00 C6 63 C2 CF | | | | | .........c..
* case 2: when hw_strip_crc=1 and UDP data is
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
(66 bytes, ie. > to 46):
dump mbuf at 0x0x7fe93bdd4fc0, phys=2dbd5040, buf_len=1920
pkt_len=108, ol_flags=2, nb_segs=1, in_port=1
segment at 0x0x7fe93bdd4fc0, data=0x0x7fe93bdd50c0, data_len=108
Dump data at [0x7fe93bdd50c0], len=108
00000000: 38 EA A7 92 70 28 58 97 BD 4F 6F C7 08 00 45 00 | 8...p(X..Oo...E.
00000010: 00 5E F3 BA 00 00 39 11 6E D9 D5 24 07 1F A3 AC | .^....9.n..$....
00000020: 9F 0B EA 5D 10 92 00 4A 58 38 61 61 61 61 61 61 | ...]...JX8aaaaaa
00000030: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | aaaaaaaaaaaaaaaa
00000040: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | aaaaaaaaaaaaaaaa
00000050: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | aaaaaaaaaaaaaaaa
00000060: 61 61 61 61 61 61 61 61 61 61 61 0A | | | | | aaaaaaaaaaa.
* case 3: when hw_strip_crc=0 and data is "aaa\n" (4 bytes):
dump mbuf at 0x0x7effcc996140, phys=2db961c0, buf_len=1920
pkt_len=60, ol_flags=2, nb_segs=1, in_port=1
segment at 0x0x7effcc996140, data=0x0x7effcc996240, data_len=60
Dump data at [0x7effcc996240], len=60
00000000: 38 EA A7 92 70 28 58 97 BD 4F 6F C7 08 00 45 00 | 8...p(X..Oo...E.
00000010: 00 20 A9 51 00 00 39 11 B9 80 D5 24 07 1F A3 AC | . .Q..9....$....
00000020: 9F 0B EA 5D 10 92 00 0C 23 7F 61 61 61 0A 00 00 | ...]....#.aaa...
00000030: 00 00 00 00 00 00 00 00 F5 8D CB 7C | | | | | ...........|
* case 4: when hw_strip_crc=1 and UDP data is
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
(66 bytes, ie. > to 46):
dump mbuf at 0x0x7effcc99ed80, phys=2db9ee00, buf_len=1920
pkt_len=108, ol_flags=2, nb_segs=1, in_port=1
segment at 0x0x7effcc99ed80, data=0x0x7effcc99ee80, data_len=108
Dump data at [0x7effcc99ee80], len=108
00000000: 38 EA A7 92 70 28 58 97 BD 4F 6F C7 08 00 45 00 | 8...p(X..Oo...E.
00000010: 00 5E 3B 4E 00 00 39 11 27 46 D5 24 07 1F A3 AC | .^;N..9.'F.$....
00000020: 9F 0B EA 5D 10 92 00 4A 58 38 61 61 61 61 61 61 | ...]...JX8aaaaaa
00000030: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | aaaaaaaaaaaaaaaa
00000040: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | aaaaaaaaaaaaaaaa
00000050: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | aaaaaaaaaaaaaaaa
00000060: 61 61 61 61 61 61 61 61 61 61 61 0A | | | | | aaaaaaaaaaa.
There are a few things I don't understand:
* in case 1, why data_len = 60 and not 56, since hw_strip_crc=1? And
why the CRC is present at the end? (C6 63 C2 CF)
* case 2 seems totally normal: the CRC is not present
* for case 3, from what I understand, if hw_strip_crc is set to 0 the
ixgbe ddriver should remove the CRC
(http://dpdk.org/browse/dpdk/tree/drivers/net/ixgbe/ixgbe_rxtx.c#n1399).
Why pkt len is 60 here? And why is the CRC present at the end (F5 8D
CB 7C)?
* case 4 seems ok, the CRC is absent, as it has been removed by the driver
The context : I am working on a NAT software using DPDK and I want to
offload as much as possible, hence the following code when emitting a
packet:
udp_hdr->dgram_cksum = 0;
pkt->ol_flags |= PKT_TX_UDP_CKSUM;
udp_hdr->dgram_cksum = rte_ipv4_phdr_cksum(ipv4_header(pkt),
pkt->ol_flags);
When I'm sending a small UDP packet (small = below the minimal size of
the ethernet payload, ie. 46 bytes), the UDP checksum is always wrong.
The output of tcpdump:
# small packet
15:02:01.536009 IP (tos 0x0, ttl 54, id 59115, offset 0, flags
[none], proto UDP (17), length 31)
213.36.7.31.59997 > 10.1.13.48.4242: [bad udp cksum 0x2cf1
-> 0xa612!] UDP, length 3
# big packet
15:11:27.240870 IP (tos 0x0, ttl 54, id 5823, offset 0, flags
[none], proto UDP (17), length 112)
213.36.7.31.59997 > 10.1.13.48.4242: [udp sum ok] UDP, length 84
This is because I only rewrite some fields (source and/or destination
IP) of the rte_mbuf structure received before transmitting it, and the
UDP checksum calculation uses the CRC that hasn't been stripped
correctly as explained above.
My device is configured by calling rte_eth_dev_configure() with the
following eth_conf structure:
static const struct rte_eth_conf eth_conf = {
.link_speed=0,
.link_duplex=0,
.rxmode = {
.mq_mode=ETH_MQ_RX_RSS,
.jumbo_frame=0,
.max_rx_pkt_len=0,
.header_split=1,
.split_hdr_size=64,
.hw_ip_checksum=1,
.hw_vlan_filter=1,
.hw_vlan_strip=1,
.hw_vlan_extend=0,
.hw_strip_crc=1,
.enable_scatter=1,
.enable_lro=0,
},
.txmode = {
.mq_mode=ETH_MQ_TX_NONE,
.pvid=0,
.hw_vlan_reject_tagged=0,
.hw_vlan_reject_untagged=0,
.hw_vlan_insert_pvid=0,
},
.lpbk_mode=0,
.rx_adv_conf = {
.rss_conf = {
.rss_key=NULL,
.rss_key_len=0,
.rss_hf = ETH_RSS_PROTO_MASK,
},
},
};
And some important details:
# lshw -class network
[...]
*-network:0
description: Ethernet controller
product: 82599ES 10-Gigabit SFI/SFP+ Network Connection
[...]
# ./dpdk_nic_bind.py --status
Network devices using DPDK-compatible driver
============================================
0000:08:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection'
drv=igb_uio unused=
[...]
Thanks,
--
Julien Castets
More information about the users
mailing list