Skip to content

Commit ef39c58

Browse files
author
logwang
committed
Fix F-Stack#100: tcp anomaly when TSO is enabled.
1.Fix the wrong ip header length and tcp header length. 2.Recalculate the pseudo header checksum and set it to tcp header.
1 parent ee61971 commit ef39c58

File tree

1 file changed

+44
-10
lines changed

1 file changed

+44
-10
lines changed

lib/ff_dpdk_if.c

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -894,8 +894,8 @@ protocol_filter(const void *data, uint16_t len)
894894
if(ntohs(hdr->ether_type) != ETHER_TYPE_IPv4)
895895
return FILTER_UNKNOWN;
896896

897-
return ff_kni_proto_filter(data + sizeof(struct ether_hdr),
898-
len - sizeof(struct ether_hdr));
897+
return ff_kni_proto_filter(data + ETHER_HDR_LEN,
898+
len - ETHER_HDR_LEN);
899899
}
900900

901901
static inline void
@@ -1254,29 +1254,63 @@ ff_dpdk_if_send(struct ff_dpdk_if_context *ctx, void *m,
12541254
struct ff_tx_offload offload = {0};
12551255
ff_mbuf_tx_offload(m, &offload);
12561256

1257+
void *data = rte_pktmbuf_mtod(head, void*);
1258+
12571259
if (offload.ip_csum) {
1258-
head->ol_flags |= PKT_TX_IP_CKSUM;
1259-
head->l2_len = sizeof(struct ether_hdr);
1260-
head->l3_len = sizeof(struct ipv4_hdr);
1260+
/* ipv6 not supported yet */
1261+
struct ipv4_hdr *iph;
1262+
int iph_len;
1263+
iph = (struct ipv4_hdr *)(data + ETHER_HDR_LEN);
1264+
iph_len = (iph->version_ihl & 0x0f) << 2;
1265+
1266+
head->ol_flags |= PKT_TX_IP_CKSUM | PKT_TX_IPV4;
1267+
head->l2_len = ETHER_HDR_LEN;
1268+
head->l3_len = iph_len;
12611269
}
12621270

12631271
if (ctx->hw_features.tx_csum_l4) {
1272+
struct ipv4_hdr *iph;
1273+
int iph_len;
1274+
iph = (struct ipv4_hdr *)(data + ETHER_HDR_LEN);
1275+
iph_len = (iph->version_ihl & 0x0f) << 2;
1276+
12641277
if (offload.tcp_csum) {
12651278
head->ol_flags |= PKT_TX_TCP_CKSUM;
1266-
head->l2_len = sizeof(struct ether_hdr);
1267-
head->l3_len = sizeof(struct ipv4_hdr);
1279+
head->l2_len = ETHER_HDR_LEN;
1280+
head->l3_len = iph_len;
12681281
}
12691282

1283+
/*
1284+
* TCP segmentation offload.
1285+
*
1286+
* - set the PKT_TX_TCP_SEG flag in mbuf->ol_flags (this flag
1287+
* implies PKT_TX_TCP_CKSUM)
1288+
* - set the flag PKT_TX_IPV4 or PKT_TX_IPV6
1289+
* - if it's IPv4, set the PKT_TX_IP_CKSUM flag and
1290+
* write the IP checksum to 0 in the packet
1291+
* - fill the mbuf offload information: l2_len,
1292+
* l3_len, l4_len, tso_segsz
1293+
* - calculate the pseudo header checksum without taking ip_len
1294+
* in account, and set it in the TCP header. Refer to
1295+
* rte_ipv4_phdr_cksum() and rte_ipv6_phdr_cksum() that can be
1296+
* used as helpers.
1297+
*/
12701298
if (offload.tso_seg_size) {
1299+
struct tcp_hdr *tcph;
1300+
int tcph_len;
1301+
tcph = (struct tcp_hdr *)((char *)iph + iph_len);
1302+
tcph_len = (tcph->data_off & 0xf0) >> 2;
1303+
tcph->cksum = rte_ipv4_phdr_cksum(iph, PKT_TX_TCP_SEG);
1304+
12711305
head->ol_flags |= PKT_TX_TCP_SEG;
1272-
head->l4_len = sizeof(struct tcp_hdr);
1306+
head->l4_len = tcph_len;
12731307
head->tso_segsz = offload.tso_seg_size;
12741308
}
12751309

12761310
if (offload.udp_csum) {
12771311
head->ol_flags |= PKT_TX_UDP_CKSUM;
1278-
head->l2_len = sizeof(struct ether_hdr);
1279-
head->l3_len = sizeof(struct ipv4_hdr);
1312+
head->l2_len = ETHER_HDR_LEN;
1313+
head->l3_len = iph_len;
12801314
}
12811315
}
12821316

0 commit comments

Comments
 (0)