@@ -19,6 +19,8 @@
#define INVALID_TCP_HDRLEN(len) \
(((len) < sizeof(struct rte_tcp_hdr)) || ((len) > MAX_TCP_HLEN))
+#define VALID_GRO_TCP_FLAGS (RTE_TCP_ACK_FLAG | RTE_TCP_PSH_FLAG | RTE_TCP_FIN_FLAG)
+
struct cmn_tcp_key {
struct rte_ether_addr eth_saddr;
struct rte_ether_addr eth_daddr;
@@ -81,11 +83,13 @@ merge_two_tcp_packets(struct gro_tcp_item *item,
struct rte_mbuf *pkt,
int cmp,
uint32_t sent_seq,
+ uint8_t tcp_flags,
uint16_t ip_id,
uint16_t l2_offset)
{
struct rte_mbuf *pkt_head, *pkt_tail, *lastseg;
uint16_t hdr_len, l2_len;
+ struct rte_tcp_hdr *tcp_hdr;
if (cmp > 0) {
pkt_head = item->firstseg;
@@ -128,6 +132,11 @@ merge_two_tcp_packets(struct gro_tcp_item *item,
/* update MBUF metadata for the merged packet */
pkt_head->nb_segs += pkt_tail->nb_segs;
pkt_head->pkt_len += pkt_tail->pkt_len;
+ if (tcp_flags != RTE_TCP_ACK_FLAG) {
+ tcp_hdr = rte_pktmbuf_mtod_offset(pkt, struct rte_tcp_hdr *,
+ l2_offset + pkt_head->l2_len + pkt_head->l3_len);
+ tcp_hdr->tcp_flags |= tcp_flags;
+ }
return 1;
}
@@ -126,6 +126,7 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt,
uint32_t item_idx;
uint32_t i, max_flow_num, remaining_flow_num;
uint8_t find;
+ uint32_t item_start_idx;
/*
* Don't process the packet whose TCP header length is greater
@@ -139,11 +140,8 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt,
tcp_hdr = (struct rte_tcp_hdr *)((char *)ipv4_hdr + pkt->l3_len);
hdr_len = pkt->l2_len + pkt->l3_len + pkt->l4_len;
- /*
- * Don't process the packet which has FIN, SYN, RST, PSH, URG, ECE
- * or CWR set.
- */
- if (tcp_hdr->tcp_flags != RTE_TCP_ACK_FLAG)
+ /* Return early if the TCP flags are not handled in GRO layer */
+ if (tcp_hdr->tcp_flags & (~(VALID_GRO_TCP_FLAGS)))
return -1;
/* trim the tail padding bytes */
@@ -183,13 +181,36 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt,
if (tbl->flows[i].start_index != INVALID_ARRAY_INDEX) {
if (is_same_tcp4_flow(tbl->flows[i].key, key)) {
find = 1;
+ item_start_idx = tbl->flows[i].start_index;
break;
}
remaining_flow_num--;
}
}
- if (find == 0) {
+ if (find == 1) {
+ /*
+ * Any packet with additional flags like PSH,FIN should be processed
+ * and flushed immediately.
+ * Hence marking the start time to 0, so that the packets will be flushed
+ * immediately in timer mode.
+ */
+ if (tcp_hdr->tcp_flags & (RTE_TCP_ACK_FLAG | RTE_TCP_PSH_FLAG | RTE_TCP_FIN_FLAG)) {
+ if (tcp_hdr->tcp_flags != RTE_TCP_ACK_FLAG)
+ tbl->items[item_start_idx].start_time = 0;
+ return process_tcp_item(pkt, tcp_hdr, tcp_dl, tbl->items,
+ tbl->flows[i].start_index,
+ &tbl->item_num, tbl->max_item_num,
+ ip_id, is_atomic, start_time);
+ } else {
+ return -1;
+ }
+ }
+ /*
+ * Add new flow to the table only if contains ACK flag with data.
+ * Do not add any packets with additional tcp flags to the GRO table
+ */
+ if (tcp_hdr->tcp_flags == RTE_TCP_ACK_FLAG) {
sent_seq = rte_be_to_cpu_32(tcp_hdr->sent_seq);
item_idx = insert_new_tcp_item(pkt, tbl->items, &tbl->item_num,
tbl->max_item_num, start_time,
@@ -200,18 +221,19 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt,
if (insert_new_flow(tbl, &key, item_idx) ==
INVALID_ARRAY_INDEX) {
/*
- * Fail to insert a new flow, so delete the
- * stored packet.
+ * Fail to insert a new flow, so delete the
+ * stored packet.
*/
- delete_tcp_item(tbl->items, item_idx, &tbl->item_num, INVALID_ARRAY_INDEX);
+ delete_tcp_item(tbl->items, item_idx, &tbl->item_num,
+ INVALID_ARRAY_INDEX);
return -1;
}
return 0;
+ } else {
+ return -1;
}
- return process_tcp_item(pkt, tcp_hdr, tcp_dl, tbl->items, tbl->flows[i].start_index,
- &tbl->item_num, tbl->max_item_num,
- ip_id, is_atomic, start_time);
+ return -1;
}
/*
@@ -101,7 +101,7 @@ process_tcp_item(struct rte_mbuf *pkt,
is_atomic);
if (cmp) {
if (merge_two_tcp_packets(&items[cur_idx],
- pkt, cmp, sent_seq, ip_id, 0))
+ pkt, cmp, sent_seq, tcp_hdr->tcp_flags, ip_id, 0))
return 1;
/*
* Fail to merge the two packets, as the packet
@@ -239,10 +239,11 @@ merge_two_vxlan_tcp4_packets(struct gro_vxlan_tcp4_item *item,
struct rte_mbuf *pkt,
int cmp,
uint32_t sent_seq,
+ uint8_t tcp_flags,
uint16_t outer_ip_id,
uint16_t ip_id)
{
- if (merge_two_tcp_packets(&item->inner_item, pkt, cmp, sent_seq,
+ if (merge_two_tcp_packets(&item->inner_item, pkt, cmp, sent_seq, tcp_flags,
ip_id, pkt->outer_l2_len +
pkt->outer_l3_len)) {
/* Update the outer IPv4 ID to the large value. */
@@ -413,7 +414,7 @@ gro_vxlan_tcp4_reassemble(struct rte_mbuf *pkt,
tcp_dl, outer_is_atomic, is_atomic);
if (cmp) {
if (merge_two_vxlan_tcp4_packets(&(tbl->items[cur_idx]),
- pkt, cmp, sent_seq,
+ pkt, cmp, sent_seq, tcp_hdr->tcp_flags,
outer_ip_id, ip_id))
return 1;
/*