LCOV - code coverage report
Current view: top level - app/test - test_reassembly_perf.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 1 400 0.2 %
Date: 2024-01-22 15:55:54 Functions: 1 21 4.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 228 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2023 Marvell.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <rte_byteorder.h>
       6                 :            : #include <rte_common.h>
       7                 :            : #include <rte_cycles.h>
       8                 :            : #include <rte_ether.h>
       9                 :            : #include <rte_hexdump.h>
      10                 :            : #include <rte_ip.h>
      11                 :            : #include <rte_ip_frag.h>
      12                 :            : #include <rte_mbuf.h>
      13                 :            : #include <rte_mbuf_pool_ops.h>
      14                 :            : #include <rte_os_shim.h>
      15                 :            : #include <rte_random.h>
      16                 :            : #include <rte_udp.h>
      17                 :            : 
      18                 :            : #include "test.h"
      19                 :            : 
      20                 :            : #define MAX_FLOWS           (1024 * 32)
      21                 :            : #define MAX_BKTS            MAX_FLOWS
      22                 :            : #define MAX_ENTRIES_PER_BKT 16
      23                 :            : #define MAX_FRAGMENTS       RTE_LIBRTE_IP_FRAG_MAX_FRAG
      24                 :            : #define MIN_FRAGMENTS       2
      25                 :            : #define MAX_PKTS            (MAX_FLOWS * MAX_FRAGMENTS)
      26                 :            : 
      27                 :            : #define MAX_PKT_LEN 2048
      28                 :            : #define MAX_TTL_MS  (5 * MS_PER_S)
      29                 :            : 
      30                 :            : /* use RFC863 Discard Protocol */
      31                 :            : #define UDP_SRC_PORT 9
      32                 :            : #define UDP_DST_PORT 9
      33                 :            : 
      34                 :            : /* use RFC5735 / RFC2544 reserved network test addresses */
      35                 :            : #define IP_SRC_ADDR(x) ((198U << 24) | (18 << 16) | (0 << 8) | (x))
      36                 :            : #define IP_DST_ADDR(x) ((198U << 24) | (18 << 16) | (1 << 15) | (x))
      37                 :            : 
      38                 :            : /* 2001:0200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180) */
      39                 :            : static uint8_t ip6_addr[16] = {32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
      40                 :            : #define IP6_VERSION 6
      41                 :            : 
      42                 :            : #define IP_DEFTTL 64 /* from RFC 1340. */
      43                 :            : 
      44                 :            : static struct rte_ip_frag_tbl *frag_tbl;
      45                 :            : static struct rte_mempool *pkt_pool;
      46                 :            : static struct rte_mbuf *mbufs[MAX_FLOWS][MAX_FRAGMENTS];
      47                 :            : static uint8_t frag_per_flow[MAX_FLOWS];
      48                 :            : static uint32_t flow_cnt;
      49                 :            : 
      50                 :            : #define FILL_MODE_LINEAR      0
      51                 :            : #define FILL_MODE_RANDOM      1
      52                 :            : #define FILL_MODE_INTERLEAVED 2
      53                 :            : 
      54                 :            : static int
      55                 :          0 : reassembly_test_setup(void)
      56                 :            : {
      57                 :          0 :         uint64_t max_ttl_cyc = (MAX_TTL_MS * rte_get_timer_hz()) / 1E3;
      58                 :            : 
      59                 :          0 :         frag_tbl = rte_ip_frag_table_create(MAX_BKTS, MAX_ENTRIES_PER_BKT,
      60                 :            :                                             MAX_BKTS * MAX_ENTRIES_PER_BKT, max_ttl_cyc,
      61                 :          0 :                                             rte_socket_id());
      62         [ #  # ]:          0 :         if (frag_tbl == NULL)
      63                 :            :                 return TEST_FAILED;
      64                 :            : 
      65                 :          0 :         rte_mbuf_set_user_mempool_ops("ring_mp_mc");
      66                 :          0 :         pkt_pool = rte_pktmbuf_pool_create(
      67                 :            :                 "reassembly_perf_pool", MAX_FLOWS * MAX_FRAGMENTS, 0, 0,
      68                 :          0 :                 RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
      69         [ #  # ]:          0 :         if (pkt_pool == NULL) {
      70                 :            :                 printf("[%s] Failed to create pkt pool\n", __func__);
      71                 :          0 :                 rte_ip_frag_table_destroy(frag_tbl);
      72                 :          0 :                 return TEST_FAILED;
      73                 :            :         }
      74                 :            : 
      75                 :            :         return TEST_SUCCESS;
      76                 :            : }
      77                 :            : 
      78                 :            : static void
      79                 :          0 : reassembly_test_teardown(void)
      80                 :            : {
      81         [ #  # ]:          0 :         if (frag_tbl != NULL)
      82                 :          0 :                 rte_ip_frag_table_destroy(frag_tbl);
      83                 :            : 
      84                 :          0 :         rte_mempool_free(pkt_pool);
      85                 :          0 : }
      86                 :            : 
      87                 :            : static void
      88                 :          0 : randomize_array_positions(void **array, uint8_t sz)
      89                 :            : {
      90                 :            :         void *tmp;
      91                 :            :         int i, j;
      92                 :            : 
      93         [ #  # ]:          0 :         if (sz == 2) {
      94                 :          0 :                 tmp = array[0];
      95                 :          0 :                 array[0] = array[1];
      96                 :          0 :                 array[1] = tmp;
      97                 :            :         } else {
      98         [ #  # ]:          0 :                 for (i = sz - 1; i > 0; i--) {
      99                 :          0 :                         j = rte_rand_max(i + 1);
     100                 :          0 :                         tmp = array[i];
     101                 :          0 :                         array[i] = array[j];
     102                 :          0 :                         array[j] = tmp;
     103                 :            :                 }
     104                 :            :         }
     105                 :          0 : }
     106                 :            : 
     107                 :            : static void
     108                 :          0 : reassembly_print_banner(const char *proto_str)
     109                 :            : {
     110                 :            :         printf("+=============================================================="
     111                 :            :                "============================================+\n");
     112                 :            :         printf("| %-32s| %-3s : %-58d|\n", proto_str, "Flow Count", MAX_FLOWS);
     113                 :            :         printf("+================+================+=============+=============+"
     114                 :            :                "========================+===================+\n");
     115                 :            :         printf("%-17s%-17s%-14s%-14s%-25s%-20s\n", "| Fragment Order",
     116                 :            :                "| Fragments/Flow", "| Outstanding", "| Cycles/Flow",
     117                 :            :                "| Cycles/Fragment insert", "| Cycles/Reassembly |");
     118                 :            :         printf("+================+================+=============+=============+"
     119                 :            :                "========================+===================+\n");
     120                 :          0 : }
     121                 :            : 
     122                 :            : static void
     123                 :          0 : ipv4_frag_fill_data(struct rte_mbuf **mbuf, uint8_t nb_frags, uint32_t flow_id,
     124                 :            :                     uint8_t fill_mode)
     125                 :            : {
     126                 :            :         struct rte_ether_hdr *eth_hdr;
     127                 :            :         struct rte_ipv4_hdr *ip_hdr;
     128                 :            :         struct rte_udp_hdr *udp_hdr;
     129                 :            :         uint16_t frag_len;
     130                 :            :         uint8_t i;
     131                 :            : 
     132                 :          0 :         frag_len = MAX_PKT_LEN / nb_frags;
     133         [ #  # ]:          0 :         if (frag_len % 8)
     134                 :          0 :                 frag_len = RTE_ALIGN_MUL_CEIL(frag_len, 8);
     135                 :            : 
     136         [ #  # ]:          0 :         for (i = 0; i < nb_frags; i++) {
     137                 :          0 :                 struct rte_mbuf *frag = mbuf[i];
     138                 :            :                 uint16_t frag_offset = 0;
     139                 :            :                 uint32_t ip_cksum;
     140                 :            :                 uint16_t pkt_len;
     141                 :            :                 uint16_t *ptr16;
     142                 :            : 
     143                 :          0 :                 frag_offset = i * (frag_len / 8);
     144                 :            : 
     145         [ #  # ]:          0 :                 if (i == nb_frags - 1)
     146                 :          0 :                         frag_len = MAX_PKT_LEN - (frag_len * (nb_frags - 1));
     147                 :            :                 else
     148                 :          0 :                         frag_offset |= RTE_IPV4_HDR_MF_FLAG;
     149                 :            : 
     150                 :            :                 rte_pktmbuf_reset_headroom(frag);
     151                 :          0 :                 eth_hdr = rte_pktmbuf_mtod(frag, struct rte_ether_hdr *);
     152                 :          0 :                 ip_hdr = rte_pktmbuf_mtod_offset(frag, struct rte_ipv4_hdr *,
     153                 :            :                                                  sizeof(struct rte_ether_hdr));
     154                 :          0 :                 udp_hdr = rte_pktmbuf_mtod_offset(
     155                 :            :                         frag, struct rte_udp_hdr *,
     156                 :            :                         sizeof(struct rte_ether_hdr) +
     157                 :            :                                 sizeof(struct rte_ipv4_hdr));
     158                 :            : 
     159                 :          0 :                 rte_ether_unformat_addr("02:00:00:00:00:01",
     160                 :            :                                         &eth_hdr->dst_addr);
     161                 :          0 :                 rte_ether_unformat_addr("02:00:00:00:00:00",
     162                 :            :                                         &eth_hdr->src_addr);
     163                 :          0 :                 eth_hdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
     164                 :            : 
     165                 :            :                 pkt_len = frag_len;
     166                 :            :                 /*
     167                 :            :                  * Initialize UDP header.
     168                 :            :                  */
     169         [ #  # ]:          0 :                 if (i == 0) {
     170                 :          0 :                         udp_hdr->src_port = rte_cpu_to_be_16(UDP_SRC_PORT);
     171                 :          0 :                         udp_hdr->dst_port = rte_cpu_to_be_16(UDP_DST_PORT);
     172         [ #  # ]:          0 :                         udp_hdr->dgram_len = rte_cpu_to_be_16(pkt_len);
     173                 :          0 :                         udp_hdr->dgram_cksum = 0; /* No UDP checksum. */
     174                 :            :                 }
     175                 :            : 
     176                 :            :                 /*
     177                 :            :                  * Initialize IP header.
     178                 :            :                  */
     179                 :          0 :                 pkt_len = (uint16_t)(pkt_len + sizeof(struct rte_ipv4_hdr));
     180                 :          0 :                 ip_hdr->version_ihl = RTE_IPV4_VHL_DEF;
     181                 :          0 :                 ip_hdr->type_of_service = 0;
     182         [ #  # ]:          0 :                 ip_hdr->fragment_offset = rte_cpu_to_be_16(frag_offset);
     183                 :          0 :                 ip_hdr->time_to_live = IP_DEFTTL;
     184                 :          0 :                 ip_hdr->next_proto_id = IPPROTO_UDP;
     185                 :          0 :                 ip_hdr->packet_id =
     186         [ #  # ]:          0 :                         rte_cpu_to_be_16((flow_id + 1) % UINT16_MAX);
     187         [ #  # ]:          0 :                 ip_hdr->total_length = rte_cpu_to_be_16(pkt_len);
     188                 :            :                 /* Using more than 32K flows will modify the 2nd octet of the IP. */
     189         [ #  # ]:          0 :                 ip_hdr->src_addr = rte_cpu_to_be_32(IP_SRC_ADDR(flow_id));
     190         [ #  # ]:          0 :                 ip_hdr->dst_addr = rte_cpu_to_be_32(IP_DST_ADDR(flow_id));
     191                 :            : 
     192                 :            :                 /*
     193                 :            :                  * Compute IP header checksum.
     194                 :            :                  */
     195                 :            :                 ptr16 = (unaligned_uint16_t *)ip_hdr;
     196                 :            :                 ip_cksum = 0;
     197                 :            :                 ip_cksum += ptr16[0];
     198                 :          0 :                 ip_cksum += ptr16[1];
     199                 :          0 :                 ip_cksum += ptr16[2];
     200                 :          0 :                 ip_cksum += ptr16[3];
     201                 :          0 :                 ip_cksum += ptr16[4];
     202                 :          0 :                 ip_cksum += ptr16[6];
     203                 :          0 :                 ip_cksum += ptr16[7];
     204                 :          0 :                 ip_cksum += ptr16[8];
     205                 :          0 :                 ip_cksum += ptr16[9];
     206                 :            : 
     207                 :            :                 /*
     208                 :            :                  * Reduce 32 bit checksum to 16 bits and complement it.
     209                 :            :                  */
     210                 :          0 :                 ip_cksum = ((ip_cksum & 0xFFFF0000) >> 16) +
     211                 :          0 :                            (ip_cksum & 0x0000FFFF);
     212         [ #  # ]:          0 :                 if (ip_cksum > 65535)
     213                 :          0 :                         ip_cksum -= 65535;
     214                 :          0 :                 ip_cksum = (~ip_cksum) & 0x0000FFFF;
     215         [ #  # ]:          0 :                 if (ip_cksum == 0)
     216                 :            :                         ip_cksum = 0xFFFF;
     217                 :          0 :                 ip_hdr->hdr_checksum = (uint16_t)ip_cksum;
     218                 :            : 
     219                 :          0 :                 frag->data_len = sizeof(struct rte_ether_hdr) + pkt_len;
     220                 :          0 :                 frag->pkt_len = frag->data_len;
     221                 :          0 :                 frag->l2_len = sizeof(struct rte_ether_hdr);
     222                 :          0 :                 frag->l3_len = sizeof(struct rte_ipv4_hdr);
     223                 :            :         }
     224                 :            : 
     225         [ #  # ]:          0 :         if (fill_mode == FILL_MODE_RANDOM)
     226                 :          0 :                 randomize_array_positions((void **)mbuf, nb_frags);
     227                 :          0 : }
     228                 :            : 
     229                 :            : static uint8_t
     230                 :            : get_rand_frags(uint8_t max_frag)
     231                 :            : {
     232                 :          0 :         uint8_t frags = rte_rand_max(max_frag + 1);
     233                 :            : 
     234                 :          0 :         return frags <= 1 ? MIN_FRAGMENTS : frags;
     235                 :            : }
     236                 :            : 
     237                 :            : static int
     238                 :          0 : ipv4_rand_frag_pkt_setup(uint8_t fill_mode, uint8_t max_frag)
     239                 :            : {
     240                 :            :         uint8_t nb_frag;
     241                 :            :         int i;
     242                 :            : 
     243         [ #  # ]:          0 :         for (i = 0; i < MAX_FLOWS; i++) {
     244                 :          0 :                 nb_frag = get_rand_frags(max_frag);
     245   [ #  #  #  # ]:          0 :                 if (rte_mempool_get_bulk(pkt_pool, (void **)mbufs[i], nb_frag) <
     246                 :            :                     0)
     247                 :            :                         return TEST_FAILED;
     248                 :          0 :                 ipv4_frag_fill_data(mbufs[i], nb_frag, i, fill_mode);
     249                 :          0 :                 frag_per_flow[i] = nb_frag;
     250                 :            :         }
     251                 :          0 :         flow_cnt = i;
     252                 :            : 
     253                 :          0 :         return TEST_SUCCESS;
     254                 :            : }
     255                 :            : 
     256                 :            : static int
     257                 :          0 : ipv4_frag_pkt_setup(uint8_t fill_mode, uint8_t nb_frag)
     258                 :            : {
     259                 :            :         int i;
     260                 :            : 
     261         [ #  # ]:          0 :         for (i = 0; i < MAX_FLOWS; i++) {
     262   [ #  #  #  # ]:          0 :                 if (rte_mempool_get_bulk(pkt_pool, (void **)mbufs[i], nb_frag) <
     263                 :            :                     0)
     264                 :            :                         return TEST_FAILED;
     265                 :          0 :                 ipv4_frag_fill_data(mbufs[i], nb_frag, i, fill_mode);
     266                 :          0 :                 frag_per_flow[i] = nb_frag;
     267                 :            :         }
     268                 :          0 :         flow_cnt = i;
     269                 :            : 
     270                 :          0 :         return TEST_SUCCESS;
     271                 :            : }
     272                 :            : 
     273                 :            : static void
     274                 :          0 : ipv6_frag_fill_data(struct rte_mbuf **mbuf, uint8_t nb_frags, uint32_t flow_id,
     275                 :            :                     uint8_t fill_mode)
     276                 :            : {
     277                 :            :         struct ipv6_extension_fragment *frag_hdr;
     278                 :            :         struct rte_ether_hdr *eth_hdr;
     279                 :            :         struct rte_ipv6_hdr *ip_hdr;
     280                 :            :         struct rte_udp_hdr *udp_hdr;
     281                 :            :         uint16_t frag_len;
     282                 :            :         uint8_t i;
     283                 :            : 
     284                 :          0 :         frag_len = MAX_PKT_LEN / nb_frags;
     285         [ #  # ]:          0 :         if (frag_len % 8)
     286                 :          0 :                 frag_len = RTE_ALIGN_MUL_CEIL(frag_len, 8);
     287                 :            : 
     288         [ #  # ]:          0 :         for (i = 0; i < nb_frags; i++) {
     289                 :          0 :                 struct rte_mbuf *frag = mbuf[i];
     290                 :            :                 uint16_t frag_offset = 0;
     291                 :            :                 uint16_t pkt_len;
     292                 :            : 
     293                 :          0 :                 frag_offset = i * (frag_len / 8);
     294                 :          0 :                 frag_offset <<= 3;
     295         [ #  # ]:          0 :                 if (i == nb_frags - 1) {
     296                 :          0 :                         frag_len = MAX_PKT_LEN - (frag_len * (nb_frags - 1));
     297                 :            :                         frag_offset = RTE_IPV6_SET_FRAG_DATA(frag_offset, 0);
     298                 :            :                 } else {
     299                 :          0 :                         frag_offset = RTE_IPV6_SET_FRAG_DATA(frag_offset, 1);
     300                 :            :                 }
     301                 :            : 
     302                 :            :                 rte_pktmbuf_reset_headroom(frag);
     303                 :          0 :                 eth_hdr = rte_pktmbuf_mtod(frag, struct rte_ether_hdr *);
     304                 :          0 :                 ip_hdr = rte_pktmbuf_mtod_offset(frag, struct rte_ipv6_hdr *,
     305                 :            :                                                  sizeof(struct rte_ether_hdr));
     306                 :          0 :                 udp_hdr = rte_pktmbuf_mtod_offset(
     307                 :            :                         frag, struct rte_udp_hdr *,
     308                 :            :                         sizeof(struct rte_ether_hdr) +
     309                 :            :                                 sizeof(struct rte_ipv6_hdr) +
     310                 :            :                                 RTE_IPV6_FRAG_HDR_SIZE);
     311                 :          0 :                 frag_hdr = rte_pktmbuf_mtod_offset(
     312                 :            :                         frag, struct ipv6_extension_fragment *,
     313                 :            :                         sizeof(struct rte_ether_hdr) +
     314                 :            :                                 sizeof(struct rte_ipv6_hdr));
     315                 :            : 
     316                 :          0 :                 rte_ether_unformat_addr("02:00:00:00:00:01",
     317                 :            :                                         &eth_hdr->dst_addr);
     318                 :          0 :                 rte_ether_unformat_addr("02:00:00:00:00:00",
     319                 :            :                                         &eth_hdr->src_addr);
     320                 :          0 :                 eth_hdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
     321                 :            : 
     322                 :            :                 pkt_len = frag_len;
     323                 :            :                 /*
     324                 :            :                  * Initialize UDP header.
     325                 :            :                  */
     326         [ #  # ]:          0 :                 if (i == 0) {
     327                 :          0 :                         udp_hdr->src_port = rte_cpu_to_be_16(UDP_SRC_PORT);
     328                 :          0 :                         udp_hdr->dst_port = rte_cpu_to_be_16(UDP_DST_PORT);
     329         [ #  # ]:          0 :                         udp_hdr->dgram_len = rte_cpu_to_be_16(pkt_len);
     330                 :          0 :                         udp_hdr->dgram_cksum = 0; /* No UDP checksum. */
     331                 :            :                 }
     332                 :            : 
     333                 :            :                 /*
     334                 :            :                  * Initialize IP header.
     335                 :            :                  */
     336                 :          0 :                 pkt_len = (uint16_t)(pkt_len + sizeof(struct rte_ipv6_hdr) +
     337                 :            :                                      RTE_IPV6_FRAG_HDR_SIZE);
     338                 :          0 :                 ip_hdr->vtc_flow = rte_cpu_to_be_32(IP6_VERSION << 28);
     339                 :          0 :                 ip_hdr->payload_len =
     340         [ #  # ]:          0 :                         rte_cpu_to_be_16(pkt_len - sizeof(struct rte_ipv6_hdr));
     341                 :          0 :                 ip_hdr->proto = IPPROTO_FRAGMENT;
     342                 :          0 :                 ip_hdr->hop_limits = IP_DEFTTL;
     343         [ #  # ]:          0 :                 memcpy(ip_hdr->src_addr, ip6_addr, sizeof(ip_hdr->src_addr));
     344                 :          0 :                 memcpy(ip_hdr->dst_addr, ip6_addr, sizeof(ip_hdr->dst_addr));
     345                 :          0 :                 ip_hdr->src_addr[7] = (flow_id >> 16) & 0xf;
     346                 :          0 :                 ip_hdr->src_addr[7] |= 0x10;
     347                 :          0 :                 ip_hdr->src_addr[8] = (flow_id >> 8) & 0xff;
     348                 :          0 :                 ip_hdr->src_addr[9] = flow_id & 0xff;
     349                 :            : 
     350                 :            :                 ip_hdr->dst_addr[7] = (flow_id >> 16) & 0xf;
     351                 :          0 :                 ip_hdr->dst_addr[7] |= 0x20;
     352                 :          0 :                 ip_hdr->dst_addr[8] = (flow_id >> 8) & 0xff;
     353                 :          0 :                 ip_hdr->dst_addr[9] = flow_id & 0xff;
     354                 :            : 
     355                 :          0 :                 frag_hdr->next_header = IPPROTO_UDP;
     356                 :          0 :                 frag_hdr->reserved = 0;
     357         [ #  # ]:          0 :                 frag_hdr->frag_data = rte_cpu_to_be_16(frag_offset);
     358         [ #  # ]:          0 :                 frag_hdr->id = rte_cpu_to_be_32(flow_id + 1);
     359                 :            : 
     360                 :          0 :                 frag->data_len = sizeof(struct rte_ether_hdr) + pkt_len;
     361                 :          0 :                 frag->pkt_len = frag->data_len;
     362                 :          0 :                 frag->l2_len = sizeof(struct rte_ether_hdr);
     363                 :          0 :                 frag->l3_len =
     364                 :            :                         sizeof(struct rte_ipv6_hdr) + RTE_IPV6_FRAG_HDR_SIZE;
     365                 :            :         }
     366                 :            : 
     367         [ #  # ]:          0 :         if (fill_mode == FILL_MODE_RANDOM)
     368                 :          0 :                 randomize_array_positions((void **)mbuf, nb_frags);
     369                 :          0 : }
     370                 :            : 
     371                 :            : static int
     372                 :          0 : ipv6_rand_frag_pkt_setup(uint8_t fill_mode, uint8_t max_frag)
     373                 :            : {
     374                 :            :         uint8_t nb_frag;
     375                 :            :         int i;
     376                 :            : 
     377         [ #  # ]:          0 :         for (i = 0; i < MAX_FLOWS; i++) {
     378                 :          0 :                 nb_frag = get_rand_frags(max_frag);
     379   [ #  #  #  # ]:          0 :                 if (rte_mempool_get_bulk(pkt_pool, (void **)mbufs[i], nb_frag) <
     380                 :            :                     0)
     381                 :            :                         return TEST_FAILED;
     382                 :          0 :                 ipv6_frag_fill_data(mbufs[i], nb_frag, i, fill_mode);
     383                 :          0 :                 frag_per_flow[i] = nb_frag;
     384                 :            :         }
     385                 :          0 :         flow_cnt = i;
     386                 :            : 
     387                 :          0 :         return TEST_SUCCESS;
     388                 :            : }
     389                 :            : 
     390                 :            : static int
     391                 :          0 : ipv6_frag_pkt_setup(uint8_t fill_mode, uint8_t nb_frag)
     392                 :            : {
     393                 :            :         int i;
     394                 :            : 
     395         [ #  # ]:          0 :         for (i = 0; i < MAX_FLOWS; i++) {
     396   [ #  #  #  # ]:          0 :                 if (rte_mempool_get_bulk(pkt_pool, (void **)mbufs[i], nb_frag) <
     397                 :            :                     0)
     398                 :            :                         return TEST_FAILED;
     399                 :          0 :                 ipv6_frag_fill_data(mbufs[i], nb_frag, i, fill_mode);
     400                 :          0 :                 frag_per_flow[i] = nb_frag;
     401                 :            :         }
     402                 :          0 :         flow_cnt = i;
     403                 :            : 
     404                 :          0 :         return TEST_SUCCESS;
     405                 :            : }
     406                 :            : 
     407                 :            : static void
     408                 :            : frag_pkt_teardown(void)
     409                 :            : {
     410                 :            :         uint32_t i;
     411                 :            : 
     412   [ #  #  #  # ]:          0 :         for (i = 0; i < flow_cnt; i++)
     413                 :          0 :                 rte_pktmbuf_free(mbufs[i][0]);
     414                 :            : }
     415                 :            : 
     416                 :            : static void
     417                 :          0 : reassembly_print_stats(int8_t nb_frags, uint8_t fill_order,
     418                 :            :                        uint32_t outstanding, uint64_t cyc_per_flow,
     419                 :            :                        uint64_t cyc_per_frag_insert,
     420                 :            :                        uint64_t cyc_per_reassembly)
     421                 :            : {
     422                 :            :         char frag_str[8], order_str[12];
     423                 :            : 
     424         [ #  # ]:          0 :         if (nb_frags > 0)
     425                 :          0 :                 snprintf(frag_str, sizeof(frag_str), "%d", nb_frags);
     426                 :            :         else
     427                 :            :                 snprintf(frag_str, sizeof(frag_str), "RANDOM");
     428                 :            : 
     429   [ #  #  #  # ]:          0 :         switch (fill_order) {
     430                 :            :         case FILL_MODE_LINEAR:
     431                 :            :                 snprintf(order_str, sizeof(order_str), "LINEAR");
     432                 :            :                 break;
     433                 :            :         case FILL_MODE_RANDOM:
     434                 :            :                 snprintf(order_str, sizeof(order_str), "RANDOM");
     435                 :            :                 break;
     436                 :            :         case FILL_MODE_INTERLEAVED:
     437                 :            :                 snprintf(order_str, sizeof(order_str), "INTERLEAVED");
     438                 :            :                 break;
     439                 :            :         default:
     440                 :            :                 break;
     441                 :            :         }
     442                 :            : 
     443                 :            :         printf("| %-14s | %-14s | %-11d | %-11" PRIu64 " | %-22" PRIu64
     444                 :            :                " | %-17" PRIu64 " |\n",
     445                 :            :                order_str, frag_str, outstanding, cyc_per_flow,
     446                 :            :                cyc_per_frag_insert, cyc_per_reassembly);
     447                 :            :         printf("+================+================+=============+=============+"
     448                 :            :                "========================+===================+\n");
     449                 :          0 : }
     450                 :            : 
     451                 :            : static void
     452                 :            : join_array(struct rte_mbuf **dest_arr, struct rte_mbuf **src_arr,
     453                 :            :            uint8_t offset, uint8_t sz)
     454                 :            : {
     455                 :            :         int i, j;
     456                 :            : 
     457   [ #  #  #  # ]:          0 :         for (i = offset, j = 0; j < sz; i++, j++)
     458                 :          0 :                 dest_arr[i] = src_arr[j];
     459                 :            : }
     460                 :            : 
     461                 :            : static int
     462                 :          0 : ipv4_reassembly_perf(int8_t nb_frags, uint8_t fill_order)
     463                 :            : {
     464                 :            :         struct rte_ip_frag_death_row death_row;
     465                 :            :         uint64_t total_reassembled_cyc = 0;
     466                 :            :         uint64_t total_empty_cyc = 0;
     467                 :            :         uint64_t tstamp, flow_tstamp;
     468                 :            :         uint64_t frag_processed = 0;
     469                 :            :         uint64_t total_cyc = 0;
     470                 :            :         uint32_t i, j;
     471                 :            : 
     472         [ #  # ]:          0 :         for (i = 0; i < flow_cnt; i++) {
     473                 :            :                 struct rte_mbuf *buf_out = NULL;
     474                 :            :                 uint8_t reassembled = 0;
     475                 :            : 
     476                 :            :                 flow_tstamp = rte_rdtsc_precise();
     477         [ #  # ]:          0 :                 for (j = 0; j < frag_per_flow[i]; j++) {
     478                 :          0 :                         struct rte_mbuf *buf = mbufs[i][j];
     479                 :          0 :                         struct rte_ipv4_hdr *ip_hdr = rte_pktmbuf_mtod_offset(
     480                 :            :                                 buf, struct rte_ipv4_hdr *, buf->l2_len);
     481                 :            : 
     482                 :            :                         tstamp = rte_rdtsc_precise();
     483                 :          0 :                         buf_out = rte_ipv4_frag_reassemble_packet(
     484                 :            :                                 frag_tbl, &death_row, buf, flow_tstamp, ip_hdr);
     485                 :            : 
     486         [ #  # ]:          0 :                         if (buf_out == NULL) {
     487                 :          0 :                                 total_empty_cyc += rte_rdtsc_precise() - tstamp;
     488                 :          0 :                                 frag_processed++;
     489                 :          0 :                                 continue;
     490                 :            :                         } else {
     491                 :            :                                 /*Packet out*/
     492                 :          0 :                                 total_reassembled_cyc +=
     493                 :          0 :                                         rte_rdtsc_precise() - tstamp;
     494                 :            :                                 reassembled = 1;
     495                 :            :                         }
     496                 :            :                 }
     497                 :          0 :                 total_cyc += rte_rdtsc_precise() - flow_tstamp;
     498   [ #  #  #  # ]:          0 :                 if (!reassembled || buf_out->nb_segs != frag_per_flow[i])
     499                 :            :                         return TEST_FAILED;
     500                 :          0 :                 memset(mbufs[i], 0, sizeof(struct rte_mbuf *) * MAX_FRAGMENTS);
     501                 :          0 :                 mbufs[i][0] = buf_out;
     502                 :            :         }
     503                 :            : 
     504                 :          0 :         reassembly_print_stats(nb_frags, fill_order, 0, total_cyc / flow_cnt,
     505                 :            :                                total_empty_cyc / frag_processed,
     506                 :            :                                total_reassembled_cyc / flow_cnt);
     507                 :            : 
     508                 :          0 :         return TEST_SUCCESS;
     509                 :            : }
     510                 :            : 
     511                 :            : static int
     512                 :          0 : ipv4_outstanding_reassembly_perf(int8_t nb_frags, uint8_t fill_order,
     513                 :            :                                  uint32_t outstanding)
     514                 :            : {
     515                 :            :         struct rte_ip_frag_death_row death_row;
     516                 :            :         uint64_t total_reassembled_cyc = 0;
     517                 :            :         uint64_t total_empty_cyc = 0;
     518                 :            :         uint64_t tstamp, flow_tstamp;
     519                 :            :         uint64_t frag_processed = 0;
     520                 :            :         uint64_t total_cyc = 0;
     521                 :            :         uint32_t i, j, k;
     522                 :            : 
     523                 :            :         k = outstanding;
     524                 :            :         /* Insert outstanding fragments */
     525   [ #  #  #  # ]:          0 :         for (i = 0; k && (i < flow_cnt); i++) {
     526                 :            :                 struct rte_mbuf *buf_out = NULL;
     527                 :            : 
     528                 :            :                 flow_tstamp = rte_rdtsc_precise();
     529         [ #  # ]:          0 :                 for (j = frag_per_flow[i] - 1; j > 0; j--) {
     530                 :          0 :                         struct rte_mbuf *buf = mbufs[i][j];
     531                 :          0 :                         struct rte_ipv4_hdr *ip_hdr = rte_pktmbuf_mtod_offset(
     532                 :            :                                 buf, struct rte_ipv4_hdr *, buf->l2_len);
     533                 :            : 
     534                 :            :                         tstamp = rte_rdtsc_precise();
     535                 :          0 :                         buf_out = rte_ipv4_frag_reassemble_packet(
     536                 :            :                                 frag_tbl, &death_row, buf, flow_tstamp, ip_hdr);
     537                 :          0 :                         total_empty_cyc += rte_rdtsc_precise() - tstamp;
     538                 :          0 :                         frag_processed++;
     539         [ #  # ]:          0 :                         if (buf_out != NULL)
     540                 :            :                                 return TEST_FAILED;
     541                 :            : 
     542                 :          0 :                         k--;
     543                 :            :                 }
     544                 :          0 :                 frag_per_flow[i] = 1;
     545                 :            :         }
     546                 :            : 
     547         [ #  # ]:          0 :         for (i = 0; i < flow_cnt; i++) {
     548                 :            :                 struct rte_mbuf *buf_out = NULL;
     549                 :            :                 uint8_t reassembled = 0;
     550                 :            : 
     551                 :            :                 flow_tstamp = rte_rdtsc_precise();
     552         [ #  # ]:          0 :                 for (j = 0; j < frag_per_flow[i]; j++) {
     553                 :          0 :                         struct rte_mbuf *buf = mbufs[i][j];
     554                 :          0 :                         struct rte_ipv4_hdr *ip_hdr = rte_pktmbuf_mtod_offset(
     555                 :            :                                 buf, struct rte_ipv4_hdr *, buf->l2_len);
     556                 :            : 
     557                 :            :                         tstamp = rte_rdtsc_precise();
     558                 :          0 :                         buf_out = rte_ipv4_frag_reassemble_packet(
     559                 :            :                                 frag_tbl, &death_row, buf, flow_tstamp, ip_hdr);
     560                 :            : 
     561         [ #  # ]:          0 :                         if (buf_out == NULL) {
     562                 :          0 :                                 total_empty_cyc += rte_rdtsc_precise() - tstamp;
     563                 :          0 :                                 frag_processed++;
     564                 :          0 :                                 continue;
     565                 :            :                         } else {
     566                 :            :                                 /*Packet out*/
     567                 :          0 :                                 total_reassembled_cyc +=
     568                 :          0 :                                         rte_rdtsc_precise() - tstamp;
     569                 :            :                                 reassembled = 1;
     570                 :            :                         }
     571                 :            :                 }
     572                 :          0 :                 total_cyc += rte_rdtsc_precise() - flow_tstamp;
     573         [ #  # ]:          0 :                 if (!reassembled)
     574                 :            :                         return TEST_FAILED;
     575                 :          0 :                 memset(mbufs[i], 0, sizeof(struct rte_mbuf *) * MAX_FRAGMENTS);
     576                 :          0 :                 mbufs[i][0] = buf_out;
     577                 :            :         }
     578                 :            : 
     579                 :          0 :         reassembly_print_stats(nb_frags, fill_order, outstanding,
     580                 :            :                                total_cyc / flow_cnt,
     581                 :            :                                total_empty_cyc / frag_processed,
     582                 :            :                                total_reassembled_cyc / flow_cnt);
     583                 :            : 
     584                 :          0 :         return TEST_SUCCESS;
     585                 :            : }
     586                 :            : 
     587                 :            : static int
     588                 :          0 : ipv4_reassembly_interleaved_flows_perf(uint8_t nb_frags)
     589                 :            : {
     590                 :            :         struct rte_ip_frag_death_row death_row;
     591                 :            :         uint64_t total_reassembled_cyc = 0;
     592                 :            :         uint64_t total_empty_cyc = 0;
     593                 :            :         uint64_t tstamp, flow_tstamp;
     594                 :            :         uint64_t frag_processed = 0;
     595                 :            :         uint64_t total_cyc = 0;
     596                 :            :         uint32_t i, j;
     597                 :            : 
     598         [ #  # ]:          0 :         for (i = 0; i < flow_cnt; i += 4) {
     599                 :          0 :                 struct rte_mbuf *buf_out[4] = {NULL};
     600                 :            :                 uint8_t reassembled = 0;
     601                 :            :                 uint8_t nb_frags = 0;
     602                 :            :                 uint8_t prev = 0;
     603                 :            : 
     604         [ #  # ]:          0 :                 for (j = 0; j < 4; j++)
     605                 :          0 :                         nb_frags += frag_per_flow[i + j];
     606                 :            : 
     607                 :          0 :                 struct rte_mbuf *buf_arr[nb_frags];
     608         [ #  # ]:          0 :                 for (j = 0; j < 4; j++) {
     609                 :          0 :                         join_array(buf_arr, mbufs[i + j], prev,
     610                 :          0 :                                    frag_per_flow[i + j]);
     611                 :          0 :                         prev += frag_per_flow[i + j];
     612                 :            :                 }
     613                 :          0 :                 randomize_array_positions((void **)buf_arr, nb_frags);
     614                 :            :                 flow_tstamp = rte_rdtsc_precise();
     615         [ #  # ]:          0 :                 for (j = 0; j < nb_frags; j++) {
     616                 :          0 :                         struct rte_mbuf *buf = buf_arr[j];
     617                 :          0 :                         struct rte_ipv4_hdr *ip_hdr = rte_pktmbuf_mtod_offset(
     618                 :            :                                 buf, struct rte_ipv4_hdr *, buf->l2_len);
     619                 :            : 
     620                 :            :                         tstamp = rte_rdtsc_precise();
     621                 :          0 :                         buf_out[reassembled] = rte_ipv4_frag_reassemble_packet(
     622                 :            :                                 frag_tbl, &death_row, buf, flow_tstamp, ip_hdr);
     623                 :            : 
     624         [ #  # ]:          0 :                         if (buf_out[reassembled] == NULL) {
     625                 :          0 :                                 total_empty_cyc += rte_rdtsc_precise() - tstamp;
     626                 :          0 :                                 frag_processed++;
     627                 :          0 :                                 continue;
     628                 :            :                         } else {
     629                 :            :                                 /*Packet out*/
     630                 :          0 :                                 total_reassembled_cyc +=
     631                 :          0 :                                         rte_rdtsc_precise() - tstamp;
     632                 :          0 :                                 reassembled++;
     633                 :            :                         }
     634                 :            :                 }
     635                 :          0 :                 total_cyc += rte_rdtsc_precise() - flow_tstamp;
     636         [ #  # ]:          0 :                 if (reassembled != 4)
     637                 :          0 :                         return TEST_FAILED;
     638         [ #  # ]:          0 :                 for (j = 0; j < 4; j++) {
     639                 :          0 :                         memset(mbufs[i + j], 0,
     640                 :            :                                sizeof(struct rte_mbuf *) * MAX_FRAGMENTS);
     641                 :          0 :                         mbufs[i + j][0] = buf_out[j];
     642                 :            :                 }
     643                 :            :         }
     644                 :            : 
     645                 :          0 :         reassembly_print_stats(nb_frags, FILL_MODE_INTERLEAVED, 0,
     646                 :            :                                total_cyc / flow_cnt,
     647                 :            :                                total_empty_cyc / frag_processed,
     648                 :            :                                total_reassembled_cyc / flow_cnt);
     649                 :            : 
     650                 :          0 :         return TEST_SUCCESS;
     651                 :            : }
     652                 :            : 
     653                 :            : static int
     654                 :          0 : ipv6_reassembly_perf(int8_t nb_frags, uint8_t fill_order)
     655                 :            : {
     656                 :            :         struct rte_ip_frag_death_row death_row;
     657                 :            :         uint64_t total_reassembled_cyc = 0;
     658                 :            :         uint64_t total_empty_cyc = 0;
     659                 :            :         uint64_t tstamp, flow_tstamp;
     660                 :            :         uint64_t frag_processed = 0;
     661                 :            :         uint64_t total_cyc = 0;
     662                 :            :         uint32_t i, j;
     663                 :            : 
     664         [ #  # ]:          0 :         for (i = 0; i < flow_cnt; i++) {
     665                 :            :                 struct rte_mbuf *buf_out = NULL;
     666                 :            :                 uint8_t reassembled = 0;
     667                 :            : 
     668                 :            :                 flow_tstamp = rte_rdtsc_precise();
     669         [ #  # ]:          0 :                 for (j = 0; j < frag_per_flow[i]; j++) {
     670                 :          0 :                         struct rte_mbuf *buf = mbufs[i][j];
     671                 :          0 :                         struct rte_ipv6_hdr *ip_hdr = rte_pktmbuf_mtod_offset(
     672                 :            :                                 buf, struct rte_ipv6_hdr *, buf->l2_len);
     673                 :          0 :                         struct ipv6_extension_fragment *frag_hdr =
     674                 :          0 :                                 rte_pktmbuf_mtod_offset(
     675                 :            :                                         buf, struct ipv6_extension_fragment *,
     676                 :            :                                         buf->l2_len +
     677                 :            :                                                 sizeof(struct rte_ipv6_hdr));
     678                 :            : 
     679                 :            :                         tstamp = rte_rdtsc_precise();
     680                 :          0 :                         buf_out = rte_ipv6_frag_reassemble_packet(
     681                 :            :                                 frag_tbl, &death_row, buf, flow_tstamp, ip_hdr,
     682                 :            :                                 frag_hdr);
     683                 :            : 
     684         [ #  # ]:          0 :                         if (buf_out == NULL) {
     685                 :          0 :                                 total_empty_cyc += rte_rdtsc_precise() - tstamp;
     686                 :          0 :                                 frag_processed++;
     687                 :          0 :                                 continue;
     688                 :            :                         } else {
     689                 :            :                                 /*Packet out*/
     690                 :          0 :                                 total_reassembled_cyc +=
     691                 :          0 :                                         rte_rdtsc_precise() - tstamp;
     692                 :            :                                 reassembled = 1;
     693                 :            :                         }
     694                 :            :                 }
     695                 :          0 :                 total_cyc += rte_rdtsc_precise() - flow_tstamp;
     696   [ #  #  #  # ]:          0 :                 if (!reassembled || buf_out->nb_segs != frag_per_flow[i])
     697                 :            :                         return TEST_FAILED;
     698                 :          0 :                 memset(mbufs[i], 0, sizeof(struct rte_mbuf *) * MAX_FRAGMENTS);
     699                 :          0 :                 mbufs[i][0] = buf_out;
     700                 :            :         }
     701                 :            : 
     702                 :          0 :         reassembly_print_stats(nb_frags, fill_order, 0, total_cyc / flow_cnt,
     703                 :            :                                total_empty_cyc / frag_processed,
     704                 :            :                                total_reassembled_cyc / flow_cnt);
     705                 :            : 
     706                 :          0 :         return TEST_SUCCESS;
     707                 :            : }
     708                 :            : 
     709                 :            : static int
     710                 :          0 : ipv6_outstanding_reassembly_perf(int8_t nb_frags, uint8_t fill_order,
     711                 :            :                                  uint32_t outstanding)
     712                 :            : {
     713                 :            :         struct rte_ip_frag_death_row death_row;
     714                 :            :         uint64_t total_reassembled_cyc = 0;
     715                 :            :         uint64_t total_empty_cyc = 0;
     716                 :            :         uint64_t tstamp, flow_tstamp;
     717                 :            :         uint64_t frag_processed = 0;
     718                 :            :         uint64_t total_cyc = 0;
     719                 :            :         uint32_t i, j, k;
     720                 :            : 
     721                 :            :         k = outstanding;
     722                 :            :         /* Insert outstanding fragments */
     723   [ #  #  #  # ]:          0 :         for (i = 0; k && (i < flow_cnt); i++) {
     724                 :            :                 struct rte_mbuf *buf_out = NULL;
     725                 :            : 
     726                 :            :                 flow_tstamp = rte_rdtsc_precise();
     727         [ #  # ]:          0 :                 for (j = frag_per_flow[i] - 1; j > 0; j--) {
     728                 :          0 :                         struct rte_mbuf *buf = mbufs[i][j];
     729                 :          0 :                         struct rte_ipv6_hdr *ip_hdr = rte_pktmbuf_mtod_offset(
     730                 :            :                                 buf, struct rte_ipv6_hdr *, buf->l2_len);
     731                 :          0 :                         struct ipv6_extension_fragment *frag_hdr =
     732                 :          0 :                                 rte_pktmbuf_mtod_offset(
     733                 :            :                                         buf, struct ipv6_extension_fragment *,
     734                 :            :                                         buf->l2_len +
     735                 :            :                                                 sizeof(struct rte_ipv6_hdr));
     736                 :            : 
     737                 :            :                         tstamp = rte_rdtsc_precise();
     738                 :          0 :                         buf_out = rte_ipv6_frag_reassemble_packet(
     739                 :            :                                 frag_tbl, &death_row, buf, flow_tstamp, ip_hdr,
     740                 :            :                                 frag_hdr);
     741                 :          0 :                         total_empty_cyc += rte_rdtsc_precise() - tstamp;
     742                 :          0 :                         frag_processed++;
     743                 :            : 
     744         [ #  # ]:          0 :                         if (buf_out != NULL)
     745                 :            :                                 return TEST_FAILED;
     746                 :            : 
     747                 :          0 :                         k--;
     748                 :            :                 }
     749                 :          0 :                 frag_per_flow[i] = 1;
     750                 :            :         }
     751                 :            : 
     752         [ #  # ]:          0 :         for (i = 0; i < flow_cnt; i++) {
     753                 :            :                 struct rte_mbuf *buf_out = NULL;
     754                 :            :                 uint8_t reassembled = 0;
     755                 :            : 
     756                 :            :                 flow_tstamp = rte_rdtsc_precise();
     757         [ #  # ]:          0 :                 for (j = 0; j < frag_per_flow[i]; j++) {
     758                 :          0 :                         struct rte_mbuf *buf = mbufs[i][j];
     759                 :          0 :                         struct rte_ipv6_hdr *ip_hdr = rte_pktmbuf_mtod_offset(
     760                 :            :                                 buf, struct rte_ipv6_hdr *, buf->l2_len);
     761                 :          0 :                         struct ipv6_extension_fragment *frag_hdr =
     762                 :          0 :                                 rte_pktmbuf_mtod_offset(
     763                 :            :                                         buf, struct ipv6_extension_fragment *,
     764                 :            :                                         buf->l2_len +
     765                 :            :                                                 sizeof(struct rte_ipv6_hdr));
     766                 :            : 
     767                 :            :                         tstamp = rte_rdtsc_precise();
     768                 :          0 :                         buf_out = rte_ipv6_frag_reassemble_packet(
     769                 :            :                                 frag_tbl, &death_row, buf, flow_tstamp, ip_hdr,
     770                 :            :                                 frag_hdr);
     771                 :            : 
     772         [ #  # ]:          0 :                         if (buf_out == NULL) {
     773                 :          0 :                                 total_empty_cyc += rte_rdtsc_precise() - tstamp;
     774                 :          0 :                                 frag_processed++;
     775                 :          0 :                                 continue;
     776                 :            :                         } else {
     777                 :            :                                 /*Packet out*/
     778                 :          0 :                                 total_reassembled_cyc +=
     779                 :          0 :                                         rte_rdtsc_precise() - tstamp;
     780                 :            :                                 reassembled = 1;
     781                 :            :                         }
     782                 :            :                 }
     783                 :          0 :                 total_cyc += rte_rdtsc_precise() - flow_tstamp;
     784         [ #  # ]:          0 :                 if (!reassembled)
     785                 :            :                         return TEST_FAILED;
     786                 :          0 :                 memset(mbufs[i], 0, sizeof(struct rte_mbuf *) * MAX_FRAGMENTS);
     787                 :          0 :                 mbufs[i][0] = buf_out;
     788                 :            :         }
     789                 :            : 
     790                 :          0 :         reassembly_print_stats(nb_frags, fill_order, outstanding,
     791                 :            :                                total_cyc / flow_cnt,
     792                 :            :                                total_empty_cyc / frag_processed,
     793                 :            :                                total_reassembled_cyc / flow_cnt);
     794                 :            : 
     795                 :          0 :         return TEST_SUCCESS;
     796                 :            : }
     797                 :            : 
     798                 :            : static int
     799                 :          0 : ipv6_reassembly_interleaved_flows_perf(int8_t nb_frags)
     800                 :            : {
     801                 :            :         struct rte_ip_frag_death_row death_row;
     802                 :            :         uint64_t total_reassembled_cyc = 0;
     803                 :            :         uint64_t total_empty_cyc = 0;
     804                 :            :         uint64_t tstamp, flow_tstamp;
     805                 :            :         uint64_t frag_processed = 0;
     806                 :            :         uint64_t total_cyc = 0;
     807                 :            :         uint32_t i, j;
     808                 :            : 
     809         [ #  # ]:          0 :         for (i = 0; i < flow_cnt; i += 4) {
     810                 :          0 :                 struct rte_mbuf *buf_out[4] = {NULL};
     811                 :            :                 uint8_t reassembled = 0;
     812                 :            :                 uint8_t nb_frags = 0;
     813                 :            :                 uint8_t prev = 0;
     814                 :            : 
     815         [ #  # ]:          0 :                 for (j = 0; j < 4; j++)
     816                 :          0 :                         nb_frags += frag_per_flow[i + j];
     817                 :            : 
     818                 :          0 :                 struct rte_mbuf *buf_arr[nb_frags];
     819         [ #  # ]:          0 :                 for (j = 0; j < 4; j++) {
     820                 :          0 :                         join_array(buf_arr, mbufs[i + j], prev,
     821                 :          0 :                                    frag_per_flow[i + j]);
     822                 :          0 :                         prev += frag_per_flow[i + j];
     823                 :            :                 }
     824                 :          0 :                 randomize_array_positions((void **)buf_arr, nb_frags);
     825                 :            :                 flow_tstamp = rte_rdtsc_precise();
     826         [ #  # ]:          0 :                 for (j = 0; j < nb_frags; j++) {
     827                 :          0 :                         struct rte_mbuf *buf = buf_arr[j];
     828                 :          0 :                         struct rte_ipv6_hdr *ip_hdr = rte_pktmbuf_mtod_offset(
     829                 :            :                                 buf, struct rte_ipv6_hdr *, buf->l2_len);
     830                 :          0 :                         struct ipv6_extension_fragment *frag_hdr =
     831                 :          0 :                                 rte_pktmbuf_mtod_offset(
     832                 :            :                                         buf, struct ipv6_extension_fragment *,
     833                 :            :                                         buf->l2_len +
     834                 :            :                                                 sizeof(struct rte_ipv6_hdr));
     835                 :            : 
     836                 :            :                         tstamp = rte_rdtsc_precise();
     837                 :          0 :                         buf_out[reassembled] = rte_ipv6_frag_reassemble_packet(
     838                 :            :                                 frag_tbl, &death_row, buf, flow_tstamp, ip_hdr,
     839                 :            :                                 frag_hdr);
     840                 :            : 
     841         [ #  # ]:          0 :                         if (buf_out[reassembled] == NULL) {
     842                 :          0 :                                 total_empty_cyc += rte_rdtsc_precise() - tstamp;
     843                 :          0 :                                 frag_processed++;
     844                 :          0 :                                 continue;
     845                 :            :                         } else {
     846                 :            :                                 /*Packet out*/
     847                 :          0 :                                 total_reassembled_cyc +=
     848                 :          0 :                                         rte_rdtsc_precise() - tstamp;
     849                 :          0 :                                 reassembled++;
     850                 :            :                         }
     851                 :            :                 }
     852                 :          0 :                 total_cyc += rte_rdtsc_precise() - flow_tstamp;
     853         [ #  # ]:          0 :                 if (reassembled != 4)
     854                 :          0 :                         return TEST_FAILED;
     855         [ #  # ]:          0 :                 for (j = 0; j < 4; j++) {
     856                 :          0 :                         memset(mbufs[i + j], 0,
     857                 :            :                                sizeof(struct rte_mbuf *) * MAX_FRAGMENTS);
     858                 :          0 :                         mbufs[i + j][0] = buf_out[j];
     859                 :            :                 }
     860                 :            :         }
     861                 :            : 
     862                 :          0 :         reassembly_print_stats(nb_frags, FILL_MODE_INTERLEAVED, 0,
     863                 :            :                                total_cyc / flow_cnt,
     864                 :            :                                total_empty_cyc / frag_processed,
     865                 :            :                                total_reassembled_cyc / flow_cnt);
     866                 :            : 
     867                 :          0 :         return TEST_SUCCESS;
     868                 :            : }
     869                 :            : 
     870                 :            : static int
     871                 :          0 : ipv4_reassembly_test(int8_t nb_frags, uint8_t fill_order, uint32_t outstanding)
     872                 :            : {
     873                 :            :         int rc;
     874                 :            : 
     875         [ #  # ]:          0 :         if (nb_frags > 0)
     876                 :          0 :                 rc = ipv4_frag_pkt_setup(fill_order, nb_frags);
     877                 :            :         else
     878                 :          0 :                 rc = ipv4_rand_frag_pkt_setup(fill_order, MAX_FRAGMENTS);
     879                 :            : 
     880         [ #  # ]:          0 :         if (rc)
     881                 :            :                 return rc;
     882                 :            : 
     883         [ #  # ]:          0 :         if (outstanding)
     884                 :          0 :                 rc = ipv4_outstanding_reassembly_perf(nb_frags, fill_order,
     885                 :            :                                                       outstanding);
     886         [ #  # ]:          0 :         else if (fill_order == FILL_MODE_INTERLEAVED)
     887                 :          0 :                 rc = ipv4_reassembly_interleaved_flows_perf(nb_frags);
     888                 :            :         else
     889                 :          0 :                 rc = ipv4_reassembly_perf(nb_frags, fill_order);
     890                 :            : 
     891                 :            :         frag_pkt_teardown();
     892                 :            : 
     893                 :            :         return rc;
     894                 :            : }
     895                 :            : 
     896                 :            : static int
     897                 :          0 : ipv6_reassembly_test(int8_t nb_frags, uint8_t fill_order, uint32_t outstanding)
     898                 :            : {
     899                 :            :         int rc;
     900                 :            : 
     901         [ #  # ]:          0 :         if (nb_frags > 0)
     902                 :          0 :                 rc = ipv6_frag_pkt_setup(fill_order, nb_frags);
     903                 :            :         else
     904                 :          0 :                 rc = ipv6_rand_frag_pkt_setup(fill_order, MAX_FRAGMENTS);
     905                 :            : 
     906         [ #  # ]:          0 :         if (rc)
     907                 :            :                 return rc;
     908                 :            : 
     909         [ #  # ]:          0 :         if (outstanding)
     910                 :          0 :                 rc = ipv6_outstanding_reassembly_perf(nb_frags, fill_order,
     911                 :            :                                                       outstanding);
     912         [ #  # ]:          0 :         else if (fill_order == FILL_MODE_INTERLEAVED)
     913                 :          0 :                 rc = ipv6_reassembly_interleaved_flows_perf(nb_frags);
     914                 :            :         else
     915                 :          0 :                 rc = ipv6_reassembly_perf(nb_frags, fill_order);
     916                 :            : 
     917                 :            :         frag_pkt_teardown();
     918                 :            : 
     919                 :            :         return rc;
     920                 :            : }
     921                 :            : 
     922                 :            : static int
     923                 :          0 : test_reassembly_perf(void)
     924                 :            : {
     925                 :          0 :         int8_t nb_fragments[] = {2, 3, MAX_FRAGMENTS, -1 /* Random */};
     926                 :          0 :         uint8_t order_type[] = {FILL_MODE_LINEAR, FILL_MODE_RANDOM};
     927                 :          0 :         uint32_t outstanding[] = {100, 500, 1000, 2000, 3000};
     928                 :            :         uint32_t i, j;
     929                 :            :         int rc;
     930                 :            : 
     931                 :          0 :         rc = reassembly_test_setup();
     932         [ #  # ]:          0 :         if (rc)
     933                 :            :                 return rc;
     934                 :            : 
     935                 :          0 :         reassembly_print_banner("IPV4");
     936                 :            :         /* Test variable fragment count and ordering. */
     937         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(nb_fragments); i++) {
     938         [ #  # ]:          0 :                 for (j = 0; j < RTE_DIM(order_type); j++) {
     939                 :          0 :                         rc = ipv4_reassembly_test(nb_fragments[i],
     940                 :          0 :                                                   order_type[j], 0);
     941         [ #  # ]:          0 :                         if (rc)
     942                 :          0 :                                 return rc;
     943                 :            :                 }
     944                 :            :         }
     945                 :            : 
     946                 :            :         /* Test outstanding fragments in the table. */
     947         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(outstanding); i++) {
     948                 :          0 :                 rc = ipv4_reassembly_test(2, 0, outstanding[i]);
     949         [ #  # ]:          0 :                 if (rc)
     950                 :          0 :                         return rc;
     951                 :            :         }
     952         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(outstanding); i++) {
     953                 :          0 :                 rc = ipv4_reassembly_test(MAX_FRAGMENTS, 0, outstanding[i]);
     954         [ #  # ]:          0 :                 if (rc)
     955                 :          0 :                         return rc;
     956                 :            :         }
     957                 :            : 
     958                 :            :         /* Test interleaved flow reassembly perf */
     959         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(nb_fragments); i++) {
     960                 :          0 :                 rc = ipv4_reassembly_test(nb_fragments[i],
     961                 :            :                                           FILL_MODE_INTERLEAVED, 0);
     962         [ #  # ]:          0 :                 if (rc)
     963                 :          0 :                         return rc;
     964                 :            :         }
     965                 :            :         printf("\n");
     966                 :          0 :         reassembly_print_banner("IPV6");
     967                 :            :         /* Test variable fragment count and ordering. */
     968         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(nb_fragments); i++) {
     969         [ #  # ]:          0 :                 for (j = 0; j < RTE_DIM(order_type); j++) {
     970                 :          0 :                         rc = ipv6_reassembly_test(nb_fragments[i],
     971                 :          0 :                                                   order_type[j], 0);
     972         [ #  # ]:          0 :                         if (rc)
     973                 :          0 :                                 return rc;
     974                 :            :                 }
     975                 :            :         }
     976                 :            : 
     977                 :            :         /* Test outstanding fragments in the table. */
     978         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(outstanding); i++) {
     979                 :          0 :                 rc = ipv6_reassembly_test(2, 0, outstanding[i]);
     980         [ #  # ]:          0 :                 if (rc)
     981                 :          0 :                         return rc;
     982                 :            :         }
     983                 :            : 
     984         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(outstanding); i++) {
     985                 :          0 :                 rc = ipv6_reassembly_test(MAX_FRAGMENTS, 0, outstanding[i]);
     986         [ #  # ]:          0 :                 if (rc)
     987                 :          0 :                         return rc;
     988                 :            :         }
     989                 :            : 
     990                 :            :         /* Test interleaved flow reassembly perf */
     991         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(nb_fragments); i++) {
     992                 :          0 :                 rc = ipv6_reassembly_test(nb_fragments[i],
     993                 :            :                                           FILL_MODE_INTERLEAVED, 0);
     994         [ #  # ]:          0 :                 if (rc)
     995                 :          0 :                         return rc;
     996                 :            :         }
     997                 :          0 :         reassembly_test_teardown();
     998                 :            : 
     999                 :          0 :         return TEST_SUCCESS;
    1000                 :            : }
    1001                 :            : 
    1002                 :        235 : REGISTER_PERF_TEST(reassembly_perf_autotest, test_reassembly_perf);

Generated by: LCOV version 1.14