LCOV - code coverage report
Current view: top level - lib/gro - gro_udp4.h (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 32 0.0 %
Date: 2025-01-02 22:41:34 Functions: 0 1 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 32 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2020 Inspur Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #ifndef _GRO_UDP4_H_
       6                 :            : #define _GRO_UDP4_H_
       7                 :            : 
       8                 :            : #include <rte_ip.h>
       9                 :            : 
      10                 :            : #define INVALID_ARRAY_INDEX 0xffffffffUL
      11                 :            : #define GRO_UDP4_TBL_MAX_ITEM_NUM (1024UL * 1024UL)
      12                 :            : 
      13                 :            : /*
      14                 :            :  * The max length of a IPv4 packet, which includes the length of the L3
      15                 :            :  * header, the L4 header and the data payload.
      16                 :            :  */
      17                 :            : #define MAX_IPV4_PKT_LENGTH UINT16_MAX
      18                 :            : 
      19                 :            : /* Header fields representing a UDP/IPv4 flow */
      20                 :            : struct udp4_flow_key {
      21                 :            :         struct rte_ether_addr eth_saddr;
      22                 :            :         struct rte_ether_addr eth_daddr;
      23                 :            :         uint32_t ip_src_addr;
      24                 :            :         uint32_t ip_dst_addr;
      25                 :            : 
      26                 :            :         /* IP fragment for UDP does not contain UDP header
      27                 :            :          * except the first one. But IP ID must be same.
      28                 :            :          */
      29                 :            :         uint16_t ip_id;
      30                 :            : };
      31                 :            : 
      32                 :            : struct gro_udp4_flow {
      33                 :            :         struct udp4_flow_key key;
      34                 :            :         /*
      35                 :            :          * The index of the first packet in the flow.
      36                 :            :          * INVALID_ARRAY_INDEX indicates an empty flow.
      37                 :            :          */
      38                 :            :         uint32_t start_index;
      39                 :            : };
      40                 :            : 
      41                 :            : struct gro_udp4_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                 :            :         /* offset of IP fragment packet */
      62                 :            :         uint16_t frag_offset;
      63                 :            :         /* is last IP fragment? */
      64                 :            :         uint8_t is_last_frag;
      65                 :            :         /* the number of merged packets */
      66                 :            :         uint16_t nb_merged;
      67                 :            : };
      68                 :            : 
      69                 :            : /*
      70                 :            :  * UDP/IPv4 reassembly table structure.
      71                 :            :  */
      72                 :            : struct gro_udp4_tbl {
      73                 :            :         /* item array */
      74                 :            :         struct gro_udp4_item *items;
      75                 :            :         /* flow array */
      76                 :            :         struct gro_udp4_flow *flows;
      77                 :            :         /* current item number */
      78                 :            :         uint32_t item_num;
      79                 :            :         /* current flow num */
      80                 :            :         uint32_t flow_num;
      81                 :            :         /* item array size */
      82                 :            :         uint32_t max_item_num;
      83                 :            :         /* flow array size */
      84                 :            :         uint32_t max_flow_num;
      85                 :            : };
      86                 :            : 
      87                 :            : /**
      88                 :            :  * This function creates a UDP/IPv4 reassembly table.
      89                 :            :  *
      90                 :            :  * @param socket_id
      91                 :            :  *  Socket index for allocating the UDP/IPv4 reassemble table
      92                 :            :  * @param max_flow_num
      93                 :            :  *  The maximum number of flows in the UDP/IPv4 GRO table
      94                 :            :  * @param max_item_per_flow
      95                 :            :  *  The maximum number of packets per flow
      96                 :            :  *
      97                 :            :  * @return
      98                 :            :  *  - Return the table pointer on success.
      99                 :            :  *  - Return NULL on failure.
     100                 :            :  */
     101                 :            : void *gro_udp4_tbl_create(uint16_t socket_id,
     102                 :            :                 uint16_t max_flow_num,
     103                 :            :                 uint16_t max_item_per_flow);
     104                 :            : 
     105                 :            : /**
     106                 :            :  * This function destroys a UDP/IPv4 reassembly table.
     107                 :            :  *
     108                 :            :  * @param tbl
     109                 :            :  *  Pointer pointing to the UDP/IPv4 reassembly table.
     110                 :            :  */
     111                 :            : void gro_udp4_tbl_destroy(void *tbl);
     112                 :            : 
     113                 :            : /**
     114                 :            :  * This function merges a UDP/IPv4 packet.
     115                 :            :  *
     116                 :            :  * This function does not check if the packet has correct checksums and
     117                 :            :  * does not re-calculate checksums for the merged packet. It returns the
     118                 :            :  * packet if it isn't UDP fragment or there is no available space in
     119                 :            :  * the table.
     120                 :            :  *
     121                 :            :  * @param pkt
     122                 :            :  *  Packet to reassemble
     123                 :            :  * @param tbl
     124                 :            :  *  Pointer pointing to the UDP/IPv4 reassembly table
     125                 :            :  * @start_time
     126                 :            :  *  The time when the packet is inserted into the table
     127                 :            :  *
     128                 :            :  * @return
     129                 :            :  *  - Return a positive value if the packet is merged.
     130                 :            :  *  - Return zero if the packet isn't merged but stored in the table.
     131                 :            :  *  - Return a negative value for invalid parameters or no available
     132                 :            :  *    space in the table.
     133                 :            :  */
     134                 :            : int32_t gro_udp4_reassemble(struct rte_mbuf *pkt,
     135                 :            :                 struct gro_udp4_tbl *tbl,
     136                 :            :                 uint64_t start_time);
     137                 :            : 
     138                 :            : /**
     139                 :            :  * This function flushes timeout packets in a UDP/IPv4 reassembly table,
     140                 :            :  * and without updating checksums.
     141                 :            :  *
     142                 :            :  * @param tbl
     143                 :            :  *  UDP/IPv4 reassembly table pointer
     144                 :            :  * @param flush_timestamp
     145                 :            :  *  Flush packets which are inserted into the table before or at the
     146                 :            :  *  flush_timestamp.
     147                 :            :  * @param out
     148                 :            :  *  Pointer array used to keep flushed packets
     149                 :            :  * @param nb_out
     150                 :            :  *  The element number in 'out'. It also determines the maximum number of
     151                 :            :  *  packets that can be flushed finally.
     152                 :            :  *
     153                 :            :  * @return
     154                 :            :  *  The number of flushed packets
     155                 :            :  */
     156                 :            : uint16_t gro_udp4_tbl_timeout_flush(struct gro_udp4_tbl *tbl,
     157                 :            :                 uint64_t flush_timestamp,
     158                 :            :                 struct rte_mbuf **out,
     159                 :            :                 uint16_t nb_out);
     160                 :            : 
     161                 :            : /**
     162                 :            :  * This function returns the number of the packets in a UDP/IPv4
     163                 :            :  * reassembly table.
     164                 :            :  *
     165                 :            :  * @param tbl
     166                 :            :  *  UDP/IPv4 reassembly table pointer
     167                 :            :  *
     168                 :            :  * @return
     169                 :            :  *  The number of packets in the table
     170                 :            :  */
     171                 :            : uint32_t gro_udp4_tbl_pkt_count(void *tbl);
     172                 :            : 
     173                 :            : /*
     174                 :            :  * Check if two UDP/IPv4 packets belong to the same flow.
     175                 :            :  */
     176                 :            : static inline int
     177                 :            : is_same_udp4_flow(struct udp4_flow_key k1, struct udp4_flow_key k2)
     178                 :            : {
     179         [ #  # ]:          0 :         return (rte_is_same_ether_addr(&k1.eth_saddr, &k2.eth_saddr) &&
     180         [ #  # ]:          0 :                         rte_is_same_ether_addr(&k1.eth_daddr, &k2.eth_daddr) &&
     181         [ #  # ]:          0 :                         (k1.ip_src_addr == k2.ip_src_addr) &&
     182   [ #  #  #  # ]:          0 :                         (k1.ip_dst_addr == k2.ip_dst_addr) &&
     183                 :            :                         (k1.ip_id == k2.ip_id));
     184                 :            : }
     185                 :            : 
     186                 :            : /*
     187                 :            :  * Merge two UDP/IPv4 packets without updating checksums.
     188                 :            :  * If cmp is larger than 0, append the new packet to the
     189                 :            :  * original packet. Otherwise, pre-pend the new packet to
     190                 :            :  * the original packet.
     191                 :            :  */
     192                 :            : static inline int
     193                 :          0 : merge_two_udp4_packets(struct gro_udp4_item *item,
     194                 :            :                 struct rte_mbuf *pkt,
     195                 :            :                 int cmp,
     196                 :            :                 uint16_t frag_offset,
     197                 :            :                 uint8_t is_last_frag,
     198                 :            :                 uint16_t l2_offset)
     199                 :            : {
     200                 :            :         struct rte_mbuf *pkt_head, *pkt_tail, *lastseg;
     201                 :            :         uint16_t hdr_len, l2_len;
     202                 :            :         uint32_t ip_len;
     203                 :            : 
     204         [ #  # ]:          0 :         if (cmp > 0) {
     205                 :          0 :                 pkt_head = item->firstseg;
     206                 :            :                 pkt_tail = pkt;
     207                 :            :         } else {
     208                 :            :                 pkt_head = pkt;
     209                 :          0 :                 pkt_tail = item->firstseg;
     210                 :            :         }
     211                 :            : 
     212                 :            :         /* check if the IPv4 packet length is greater than the max value */
     213                 :          0 :         hdr_len = l2_offset + pkt_head->l2_len + pkt_head->l3_len;
     214         [ #  # ]:          0 :         l2_len = l2_offset > 0 ? pkt_head->outer_l2_len : pkt_head->l2_len;
     215                 :          0 :         ip_len = pkt_head->pkt_len - l2_len
     216                 :          0 :                  + pkt_tail->pkt_len - hdr_len;
     217         [ #  # ]:          0 :         if (unlikely(ip_len > MAX_IPV4_PKT_LENGTH))
     218                 :            :                 return 0;
     219                 :            : 
     220                 :            :         /* remove the packet header for the tail packet */
     221                 :            :         rte_pktmbuf_adj(pkt_tail, hdr_len);
     222                 :            : 
     223                 :            :         /* chain two packets together */
     224         [ #  # ]:          0 :         if (cmp > 0) {
     225                 :          0 :                 item->lastseg->next = pkt;
     226                 :          0 :                 item->lastseg = rte_pktmbuf_lastseg(pkt);
     227                 :            :         } else {
     228                 :            :                 lastseg = rte_pktmbuf_lastseg(pkt);
     229                 :          0 :                 lastseg->next = item->firstseg;
     230                 :          0 :                 item->firstseg = pkt;
     231                 :          0 :                 item->frag_offset = frag_offset;
     232                 :            :         }
     233                 :          0 :         item->nb_merged++;
     234         [ #  # ]:          0 :         if (is_last_frag)
     235                 :          0 :                 item->is_last_frag = is_last_frag;
     236                 :            : 
     237                 :            :         /* update MBUF metadata for the merged packet */
     238                 :          0 :         pkt_head->nb_segs += pkt_tail->nb_segs;
     239                 :          0 :         pkt_head->pkt_len += pkt_tail->pkt_len;
     240                 :            : 
     241                 :          0 :         return 1;
     242                 :            : }
     243                 :            : 
     244                 :            : /*
     245                 :            :  * Check if two UDP/IPv4 packets are neighbors.
     246                 :            :  */
     247                 :            : static inline int
     248                 :            : udp4_check_neighbor(struct gro_udp4_item *item,
     249                 :            :                 uint16_t frag_offset,
     250                 :            :                 uint16_t ip_dl,
     251                 :            :                 uint16_t l2_offset)
     252                 :            : {
     253                 :          0 :         struct rte_mbuf *pkt_orig = item->firstseg;
     254                 :            :         uint16_t len;
     255                 :            : 
     256                 :            :         /* check if the two packets are neighbors */
     257                 :          0 :         len = pkt_orig->pkt_len - l2_offset - pkt_orig->l2_len -
     258                 :          0 :                 pkt_orig->l3_len;
     259   [ #  #  #  # ]:          0 :         if (frag_offset == item->frag_offset + len)
     260                 :            :                 /* append the new packet */
     261                 :            :                 return 1;
     262   [ #  #  #  # ]:          0 :         else if (frag_offset + ip_dl == item->frag_offset)
     263                 :            :                 /* pre-pend the new packet */
     264                 :            :                 return -1;
     265                 :            : 
     266                 :            :         return 0;
     267                 :            : }
     268                 :            : 
     269                 :            : static inline int
     270                 :            : is_ipv4_fragment(const struct rte_ipv4_hdr *hdr)
     271                 :            : {
     272                 :            :         uint16_t flag_offset, ip_flag, ip_ofs;
     273                 :            : 
     274         [ #  # ]:          0 :         flag_offset = rte_be_to_cpu_16(hdr->fragment_offset);
     275                 :            :         ip_ofs = (uint16_t)(flag_offset & RTE_IPV4_HDR_OFFSET_MASK);
     276                 :            :         ip_flag = (uint16_t)(flag_offset & RTE_IPV4_HDR_MF_FLAG);
     277                 :            : 
     278         [ #  # ]:          0 :         return ip_flag != 0 || ip_ofs  != 0;
     279                 :            : }
     280                 :            : #endif

Generated by: LCOV version 1.14