LCOV - code coverage report
Current view: top level - lib/gro - gro_tcp.h (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 40 0.0 %
Date: 2025-02-01 18:54:23 Functions: 0 2 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 34 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2023 Intel Corporation
       3                 :            :  */
       4                 :            : #ifndef _GRO_TCP_H_
       5                 :            : #define _GRO_TCP_H_
       6                 :            : 
       7                 :            : #define INVALID_ARRAY_INDEX 0xffffffffUL
       8                 :            : 
       9                 :            : #include <rte_tcp.h>
      10                 :            : 
      11                 :            : /*
      12                 :            :  * The max length of a IPv4 packet, which includes the length of the L3
      13                 :            :  * header, the L4 header and the data payload.
      14                 :            :  */
      15                 :            : #define MAX_IP_PKT_LENGTH UINT16_MAX
      16                 :            : 
      17                 :            : /* The maximum TCP header length */
      18                 :            : #define MAX_TCP_HLEN 60
      19                 :            : #define INVALID_TCP_HDRLEN(len) \
      20                 :            :         (((len) < sizeof(struct rte_tcp_hdr)) || ((len) > MAX_TCP_HLEN))
      21                 :            : 
      22                 :            : #define VALID_GRO_TCP_FLAGS (RTE_TCP_ACK_FLAG | RTE_TCP_PSH_FLAG | RTE_TCP_FIN_FLAG)
      23                 :            : 
      24                 :            : struct cmn_tcp_key {
      25                 :            :         struct rte_ether_addr eth_saddr;
      26                 :            :         struct rte_ether_addr eth_daddr;
      27                 :            :         uint32_t recv_ack;
      28                 :            :         uint16_t src_port;
      29                 :            :         uint16_t dst_port;
      30                 :            : };
      31                 :            : 
      32                 :            : #define ASSIGN_COMMON_TCP_KEY(k1, k2) \
      33                 :            :         do {\
      34                 :            :                 rte_ether_addr_copy(&(k1->eth_saddr), &(k2->eth_saddr)); \
      35                 :            :                 rte_ether_addr_copy(&(k1->eth_daddr), &(k2->eth_daddr)); \
      36                 :            :                 k2->recv_ack = k1->recv_ack; \
      37                 :            :                 k2->src_port = k1->src_port; \
      38                 :            :                 k2->dst_port = k1->dst_port; \
      39                 :            :         } while (0)
      40                 :            : 
      41                 :            : struct gro_tcp_item {
      42                 :            :         /*
      43                 :            :          * The first MBUF segment of the packet. If the value
      44                 :            :          * is NULL, it means the item is empty.
      45                 :            :          */
      46                 :            :         struct rte_mbuf *firstseg;
      47                 :            :         /* The last MBUF segment of the packet */
      48                 :            :         struct rte_mbuf *lastseg;
      49                 :            :         /*
      50                 :            :          * The time when the first packet is inserted into the table.
      51                 :            :          * This value won't be updated, even if the packet is merged
      52                 :            :          * with other packets.
      53                 :            :          */
      54                 :            :         uint64_t start_time;
      55                 :            :         /*
      56                 :            :          * next_pkt_idx is used to chain the packets that
      57                 :            :          * are in the same flow but can't be merged together
      58                 :            :          * (e.g. caused by packet reordering).
      59                 :            :          */
      60                 :            :         uint32_t next_pkt_idx;
      61                 :            :         /* TCP sequence number of the packet */
      62                 :            :         uint32_t sent_seq;
      63                 :            :         union {
      64                 :            :                 /* IPv4 ID of the packet */
      65                 :            :                 uint16_t ip_id;
      66                 :            :                 /* Unused field for IPv6 */
      67                 :            :                 uint16_t unused;
      68                 :            :         } l3;
      69                 :            :         /* the number of merged packets */
      70                 :            :         uint16_t nb_merged;
      71                 :            :         /* Indicate if IPv4 ID can be ignored */
      72                 :            :         uint8_t is_atomic;
      73                 :            : };
      74                 :            : 
      75                 :            : /*
      76                 :            :  * Merge two TCP packets without updating checksums.
      77                 :            :  * If cmp is larger than 0, append the new packet to the
      78                 :            :  * original packet. Otherwise, pre-pend the new packet to
      79                 :            :  * the original packet.
      80                 :            :  */
      81                 :            : static inline int
      82                 :          0 : merge_two_tcp_packets(struct gro_tcp_item *item,
      83                 :            :                 struct rte_mbuf *pkt,
      84                 :            :                 int cmp,
      85                 :            :                 uint32_t sent_seq,
      86                 :            :                 uint8_t tcp_flags,
      87                 :            :                 uint16_t ip_id,
      88                 :            :                 uint16_t l2_offset)
      89                 :            : {
      90                 :            :         struct rte_mbuf *pkt_head, *pkt_tail, *lastseg;
      91                 :            :         uint16_t hdr_len, l2_len;
      92                 :            :         struct rte_tcp_hdr *tcp_hdr;
      93                 :            : 
      94         [ #  # ]:          0 :         if (cmp > 0) {
      95                 :          0 :                 pkt_head = item->firstseg;
      96                 :            :                 pkt_tail = pkt;
      97                 :            :         } else {
      98                 :            :                 pkt_head = pkt;
      99                 :          0 :                 pkt_tail = item->firstseg;
     100                 :            :         }
     101                 :            : 
     102                 :            :         /* check if the IPv4 packet length is greater than the max value */
     103                 :          0 :         hdr_len = l2_offset + pkt_head->l2_len + pkt_head->l3_len +
     104                 :          0 :                 pkt_head->l4_len;
     105         [ #  # ]:          0 :         l2_len = l2_offset > 0 ? pkt_head->outer_l2_len : pkt_head->l2_len;
     106         [ #  # ]:          0 :         if (unlikely(pkt_head->pkt_len - l2_len + pkt_tail->pkt_len -
     107                 :            :                                 hdr_len > MAX_IP_PKT_LENGTH))
     108                 :            :                 return 0;
     109                 :            : 
     110         [ #  # ]:          0 :         if (unlikely(pkt_head->nb_segs >= 20))
     111                 :            :                 return 0;
     112                 :            : 
     113                 :            :         /* remove the packet header for the tail packet */
     114                 :            :         rte_pktmbuf_adj(pkt_tail, hdr_len);
     115                 :            : 
     116                 :            :         /* chain two packets together */
     117         [ #  # ]:          0 :         if (cmp > 0) {
     118                 :          0 :                 item->lastseg->next = pkt;
     119                 :          0 :                 item->lastseg = rte_pktmbuf_lastseg(pkt);
     120                 :            :                 /* update IP ID to the larger value */
     121                 :          0 :                 item->l3.ip_id = ip_id;
     122                 :            :         } else {
     123                 :            :                 lastseg = rte_pktmbuf_lastseg(pkt);
     124                 :          0 :                 lastseg->next = item->firstseg;
     125                 :          0 :                 item->firstseg = pkt;
     126                 :            :                 /* update sent_seq to the smaller value */
     127                 :          0 :                 item->sent_seq = sent_seq;
     128                 :          0 :                 item->l3.ip_id = ip_id;
     129                 :            :         }
     130                 :          0 :         item->nb_merged++;
     131                 :            : 
     132                 :            :         /* update MBUF metadata for the merged packet */
     133                 :          0 :         pkt_head->nb_segs += pkt_tail->nb_segs;
     134                 :          0 :         pkt_head->pkt_len += pkt_tail->pkt_len;
     135         [ #  # ]:          0 :         if (tcp_flags != RTE_TCP_ACK_FLAG) {
     136                 :          0 :                 tcp_hdr = rte_pktmbuf_mtod_offset(pkt, struct rte_tcp_hdr *,
     137                 :            :                                                 l2_offset + pkt_head->l2_len + pkt_head->l3_len);
     138                 :          0 :                 tcp_hdr->tcp_flags |= tcp_flags;
     139                 :            :         }
     140                 :            : 
     141                 :            :         return 1;
     142                 :            : }
     143                 :            : 
     144                 :            : /*
     145                 :            :  * Check if two TCP packets are neighbors.
     146                 :            :  */
     147                 :            : static inline int
     148                 :          0 : check_seq_option(struct gro_tcp_item *item,
     149                 :            :                 struct rte_tcp_hdr *tcph,
     150                 :            :                 uint32_t sent_seq,
     151                 :            :                 uint16_t ip_id,
     152                 :            :                 uint16_t tcp_hl,
     153                 :            :                 uint16_t tcp_dl,
     154                 :            :                 uint16_t l2_offset,
     155                 :            :                 uint8_t is_atomic)
     156                 :            : {
     157                 :          0 :         struct rte_mbuf *pkt_orig = item->firstseg;
     158                 :            :         char *iph_orig;
     159                 :            :         struct rte_tcp_hdr *tcph_orig;
     160                 :            :         uint16_t len, tcp_hl_orig;
     161                 :            : 
     162                 :          0 :         iph_orig = rte_pktmbuf_mtod_offset(pkt_orig, char *,
     163                 :            :                                            l2_offset + pkt_orig->l2_len);
     164                 :          0 :         tcph_orig = (struct rte_tcp_hdr *)(iph_orig + pkt_orig->l3_len);
     165                 :          0 :         tcp_hl_orig = pkt_orig->l4_len;
     166                 :            : 
     167                 :            :         /* Check if TCP option fields equal */
     168                 :          0 :         len = RTE_MAX(tcp_hl, tcp_hl_orig) - sizeof(struct rte_tcp_hdr);
     169   [ #  #  #  # ]:          0 :         if ((tcp_hl != tcp_hl_orig) || ((len > 0) &&
     170         [ #  # ]:          0 :                                 (memcmp(tcph + 1, tcph_orig + 1,
     171                 :            :                                         len) != 0)))
     172                 :            :                 return 0;
     173                 :            : 
     174                 :            :         /* Don't merge packets whose DF bits are different */
     175         [ #  # ]:          0 :         if (unlikely(item->is_atomic ^ is_atomic))
     176                 :            :                 return 0;
     177                 :            : 
     178                 :            :         /* check if the two packets are neighbors */
     179                 :          0 :         len = pkt_orig->pkt_len - l2_offset - pkt_orig->l2_len -
     180                 :          0 :                 pkt_orig->l3_len - tcp_hl_orig;
     181   [ #  #  #  # ]:          0 :         if ((sent_seq == item->sent_seq + len) && (is_atomic ||
     182         [ #  # ]:          0 :                                 (ip_id == item->l3.ip_id + 1)))
     183                 :            :                 /* append the new packet */
     184                 :            :                 return 1;
     185   [ #  #  #  # ]:          0 :         else if ((sent_seq + tcp_dl == item->sent_seq) && (is_atomic ||
     186         [ #  # ]:          0 :                                 (ip_id + item->nb_merged == item->l3.ip_id)))
     187                 :            :                 /* pre-pend the new packet */
     188                 :          0 :                 return -1;
     189                 :            : 
     190                 :            :         return 0;
     191                 :            : }
     192                 :            : 
     193                 :            : static inline int
     194                 :            : is_same_common_tcp_key(struct cmn_tcp_key *k1, struct cmn_tcp_key *k2)
     195                 :            : {
     196         [ #  # ]:          0 :         return (!memcmp(k1, k2, sizeof(struct cmn_tcp_key)));
     197                 :            : }
     198                 :            : 
     199                 :            : #endif

Generated by: LCOV version 1.14