X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_gro%2Fgro_tcp4.c;h=20f2ea7e685dd7758d1ee070b1f1ce260d365f50;hb=24ac604ef7469eb5773c2504b313dd00257f8df3;hp=a38a06e0b678d07eed072ef2ff98bca7518f6c26;hpb=1e4cf4d6d4fb9786d2b0772867f2158ac90f55d6;p=dpdk.git diff --git a/lib/librte_gro/gro_tcp4.c b/lib/librte_gro/gro_tcp4.c index a38a06e0b6..20f2ea7e68 100644 --- a/lib/librte_gro/gro_tcp4.c +++ b/lib/librte_gro/gro_tcp4.c @@ -6,8 +6,6 @@ #include #include #include -#include -#include #include "gro_tcp4.h" @@ -74,103 +72,6 @@ gro_tcp4_tbl_destroy(void *tbl) rte_free(tcp_tbl); } -/* - * merge two TCP/IPv4 packets without updating checksums. - * If cmp is larger than 0, append the new packet to the - * original packet. Otherwise, pre-pend the new packet to - * the original packet. - */ -static inline int -merge_two_tcp4_packets(struct gro_tcp4_item *item, - struct rte_mbuf *pkt, - int cmp, - uint32_t sent_seq, - uint16_t ip_id) -{ - struct rte_mbuf *pkt_head, *pkt_tail, *lastseg; - uint16_t hdr_len; - - if (cmp > 0) { - pkt_head = item->firstseg; - pkt_tail = pkt; - } else { - pkt_head = pkt; - pkt_tail = item->firstseg; - } - - /* check if the IPv4 packet length is greater than the max value */ - hdr_len = pkt_head->l2_len + pkt_head->l3_len + pkt_head->l4_len; - if (unlikely(pkt_head->pkt_len - pkt_head->l2_len + pkt_tail->pkt_len - - hdr_len > MAX_IPV4_PKT_LENGTH)) - return 0; - - /* remove the packet header for the tail packet */ - rte_pktmbuf_adj(pkt_tail, hdr_len); - - /* chain two packets together */ - if (cmp > 0) { - item->lastseg->next = pkt; - item->lastseg = rte_pktmbuf_lastseg(pkt); - /* update IP ID to the larger value */ - item->ip_id = ip_id; - } else { - lastseg = rte_pktmbuf_lastseg(pkt); - lastseg->next = item->firstseg; - item->firstseg = pkt; - /* update sent_seq to the smaller value */ - item->sent_seq = sent_seq; - } - item->nb_merged++; - - /* update mbuf metadata for the merged packet */ - pkt_head->nb_segs += pkt_tail->nb_segs; - pkt_head->pkt_len += pkt_tail->pkt_len; - - return 1; -} - -/* - * Check if two TCP/IPv4 packets are neighbors. - */ -static inline int -check_seq_option(struct gro_tcp4_item *item, - struct tcp_hdr *tcph, - uint32_t sent_seq, - uint16_t ip_id, - uint16_t tcp_hl, - uint16_t tcp_dl) -{ - struct rte_mbuf *pkt_orig = item->firstseg; - struct ipv4_hdr *iph_orig; - struct tcp_hdr *tcph_orig; - uint16_t len, tcp_hl_orig; - - iph_orig = (struct ipv4_hdr *)(rte_pktmbuf_mtod(pkt_orig, char *) + - pkt_orig->l2_len); - tcph_orig = (struct tcp_hdr *)((char *)iph_orig + pkt_orig->l3_len); - tcp_hl_orig = pkt_orig->l4_len; - - /* Check if TCP option fields equal */ - len = RTE_MAX(tcp_hl, tcp_hl_orig) - sizeof(struct tcp_hdr); - if ((tcp_hl != tcp_hl_orig) || - ((len > 0) && (memcmp(tcph + 1, tcph_orig + 1, - len) != 0))) - return 0; - - /* check if the two packets are neighbors */ - len = pkt_orig->pkt_len - pkt_orig->l2_len - pkt_orig->l3_len - - tcp_hl_orig; - if ((sent_seq == item->sent_seq + len) && (ip_id == item->ip_id + 1)) - /* append the new packet */ - return 1; - else if ((sent_seq + tcp_dl == item->sent_seq) && - (ip_id + item->nb_merged == item->ip_id)) - /* pre-pend the new packet */ - return -1; - - return 0; -} - static inline uint32_t find_an_empty_item(struct gro_tcp4_tbl *tbl) { @@ -201,7 +102,8 @@ insert_new_item(struct gro_tcp4_tbl *tbl, uint64_t start_time, uint32_t prev_idx, uint32_t sent_seq, - uint16_t ip_id) + uint16_t ip_id, + uint8_t is_atomic) { uint32_t item_idx; @@ -216,6 +118,7 @@ insert_new_item(struct gro_tcp4_tbl *tbl, tbl->items[item_idx].sent_seq = sent_seq; tbl->items[item_idx].ip_id = ip_id; tbl->items[item_idx].nb_merged = 1; + tbl->items[item_idx].is_atomic = is_atomic; tbl->item_num++; /* if the previous packet exists, chain them together. */ @@ -257,8 +160,8 @@ insert_new_flow(struct gro_tcp4_tbl *tbl, dst = &(tbl->flows[flow_idx].key); - ether_addr_copy(&(src->eth_saddr), &(dst->eth_saddr)); - ether_addr_copy(&(src->eth_daddr), &(dst->eth_daddr)); + rte_ether_addr_copy(&(src->eth_saddr), &(dst->eth_saddr)); + rte_ether_addr_copy(&(src->eth_daddr), &(dst->eth_daddr)); dst->ip_src_addr = src->ip_src_addr; dst->ip_dst_addr = src->ip_dst_addr; dst->recv_ack = src->recv_ack; @@ -271,31 +174,16 @@ insert_new_flow(struct gro_tcp4_tbl *tbl, return flow_idx; } -/* - * Check if two TCP/IPv4 packets belong to the same flow. - */ -static inline int -is_same_tcp4_flow(struct tcp4_flow_key k1, struct tcp4_flow_key k2) -{ - return (is_same_ether_addr(&k1.eth_saddr, &k2.eth_saddr) && - is_same_ether_addr(&k1.eth_daddr, &k2.eth_daddr) && - (k1.ip_src_addr == k2.ip_src_addr) && - (k1.ip_dst_addr == k2.ip_dst_addr) && - (k1.recv_ack == k2.recv_ack) && - (k1.src_port == k2.src_port) && - (k1.dst_port == k2.dst_port)); -} - /* * update the packet length for the flushed packet. */ static inline void update_header(struct gro_tcp4_item *item) { - struct ipv4_hdr *ipv4_hdr; + struct rte_ipv4_hdr *ipv4_hdr; struct rte_mbuf *pkt = item->firstseg; - ipv4_hdr = (struct ipv4_hdr *)(rte_pktmbuf_mtod(pkt, char *) + + ipv4_hdr = (struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(pkt, char *) + pkt->l2_len); ipv4_hdr->total_length = rte_cpu_to_be_16(pkt->pkt_len - pkt->l2_len); @@ -306,11 +194,13 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, struct gro_tcp4_tbl *tbl, uint64_t start_time) { - struct ether_hdr *eth_hdr; - struct ipv4_hdr *ipv4_hdr; + struct rte_ether_hdr *eth_hdr; + struct rte_ipv4_hdr *ipv4_hdr; struct tcp_hdr *tcp_hdr; uint32_t sent_seq; - uint16_t tcp_dl, ip_id, hdr_len; + int32_t tcp_dl; + uint16_t ip_id, hdr_len, frag_off; + uint8_t is_atomic; struct tcp4_flow_key key; uint32_t cur_idx, prev_idx, item_idx; @@ -318,8 +208,15 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, int cmp; uint8_t find; - eth_hdr = rte_pktmbuf_mtod(pkt, struct ether_hdr *); - ipv4_hdr = (struct ipv4_hdr *)((char *)eth_hdr + pkt->l2_len); + /* + * Don't process the packet whose TCP header length is greater + * than 60 bytes or less than 20 bytes. + */ + if (unlikely(INVALID_TCP_HDRLEN(pkt->l4_len))) + return -1; + + eth_hdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *); + ipv4_hdr = (struct rte_ipv4_hdr *)((char *)eth_hdr + pkt->l2_len); tcp_hdr = (struct tcp_hdr *)((char *)ipv4_hdr + pkt->l3_len); hdr_len = pkt->l2_len + pkt->l3_len + pkt->l4_len; @@ -337,11 +234,17 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, if (tcp_dl <= 0) return -1; - ip_id = rte_be_to_cpu_16(ipv4_hdr->packet_id); + /* + * Save IPv4 ID for the packet whose DF bit is 0. For the packet + * whose DF bit is 1, IPv4 ID is ignored. + */ + frag_off = rte_be_to_cpu_16(ipv4_hdr->fragment_offset); + is_atomic = (frag_off & RTE_IPV4_HDR_DF_FLAG) == RTE_IPV4_HDR_DF_FLAG; + ip_id = is_atomic ? 0 : rte_be_to_cpu_16(ipv4_hdr->packet_id); sent_seq = rte_be_to_cpu_32(tcp_hdr->sent_seq); - ether_addr_copy(&(eth_hdr->s_addr), &(key.eth_saddr)); - ether_addr_copy(&(eth_hdr->d_addr), &(key.eth_daddr)); + rte_ether_addr_copy(&(eth_hdr->s_addr), &(key.eth_saddr)); + rte_ether_addr_copy(&(eth_hdr->d_addr), &(key.eth_daddr)); key.ip_src_addr = ipv4_hdr->src_addr; key.ip_dst_addr = ipv4_hdr->dst_addr; key.src_port = tcp_hdr->src_port; @@ -368,7 +271,8 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, */ if (find == 0) { item_idx = insert_new_item(tbl, pkt, start_time, - INVALID_ARRAY_INDEX, sent_seq, ip_id); + INVALID_ARRAY_INDEX, sent_seq, ip_id, + is_atomic); if (item_idx == INVALID_ARRAY_INDEX) return -1; if (insert_new_flow(tbl, &key, item_idx) == @@ -391,10 +295,11 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, prev_idx = cur_idx; do { cmp = check_seq_option(&(tbl->items[cur_idx]), tcp_hdr, - sent_seq, ip_id, pkt->l4_len, tcp_dl); + sent_seq, ip_id, pkt->l4_len, tcp_dl, 0, + is_atomic); if (cmp) { if (merge_two_tcp4_packets(&(tbl->items[cur_idx]), - pkt, cmp, sent_seq, ip_id)) + pkt, cmp, sent_seq, ip_id, 0)) return 1; /* * Fail to merge the two packets, as the packet @@ -402,7 +307,7 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, * the packet into the flow. */ if (insert_new_item(tbl, pkt, start_time, prev_idx, - sent_seq, ip_id) == + sent_seq, ip_id, is_atomic) == INVALID_ARRAY_INDEX) return -1; return 0; @@ -413,7 +318,7 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, /* Fail to find a neighbor, so store the packet into the flow. */ if (insert_new_item(tbl, pkt, start_time, prev_idx, sent_seq, - ip_id) == INVALID_ARRAY_INDEX) + ip_id, is_atomic) == INVALID_ARRAY_INDEX) return -1; return 0;