dpdk/app/test/packet_burst_generator.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2010-2014 Intel Corporation
   3 */
   4
   5#include <rte_byteorder.h>
   6#include <rte_mbuf.h>
   7#include <rte_ip.h>
   8
   9#include "packet_burst_generator.h"
  10
  11#define UDP_SRC_PORT 1024
  12#define UDP_DST_PORT 1024
  13
  14
  15#define IP_DEFTTL  64   /* from RFC 1340. */
  16
  17static void
  18copy_buf_to_pkt_segs(void *buf, unsigned len, struct rte_mbuf *pkt,
  19                unsigned offset)
  20{
  21        struct rte_mbuf *seg;
  22        void *seg_buf;
  23        unsigned copy_len;
  24
  25        seg = pkt;
  26        while (offset >= seg->data_len) {
  27                offset -= seg->data_len;
  28                seg = seg->next;
  29        }
  30        copy_len = seg->data_len - offset;
  31        seg_buf = rte_pktmbuf_mtod_offset(seg, char *, offset);
  32        while (len > copy_len) {
  33                rte_memcpy(seg_buf, buf, (size_t) copy_len);
  34                len -= copy_len;
  35                buf = ((char *) buf + copy_len);
  36                seg = seg->next;
  37                seg_buf = rte_pktmbuf_mtod(seg, void *);
  38        }
  39        rte_memcpy(seg_buf, buf, (size_t) len);
  40}
  41
  42static inline void
  43copy_buf_to_pkt(void *buf, unsigned len, struct rte_mbuf *pkt, unsigned offset)
  44{
  45        if (offset + len <= pkt->data_len) {
  46                rte_memcpy(rte_pktmbuf_mtod_offset(pkt, char *, offset), buf,
  47                           (size_t) len);
  48                return;
  49        }
  50        copy_buf_to_pkt_segs(buf, len, pkt, offset);
  51}
  52
  53void
  54initialize_eth_header(struct rte_ether_hdr *eth_hdr,
  55                struct rte_ether_addr *src_mac,
  56                struct rte_ether_addr *dst_mac, uint16_t ether_type,
  57                uint8_t vlan_enabled, uint16_t van_id)
  58{
  59        rte_ether_addr_copy(dst_mac, &eth_hdr->dst_addr);
  60        rte_ether_addr_copy(src_mac, &eth_hdr->src_addr);
  61
  62        if (vlan_enabled) {
  63                struct rte_vlan_hdr *vhdr = (struct rte_vlan_hdr *)(
  64                        (uint8_t *)eth_hdr + sizeof(struct rte_ether_hdr));
  65
  66                eth_hdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
  67
  68                vhdr->eth_proto =  rte_cpu_to_be_16(ether_type);
  69                vhdr->vlan_tci = van_id;
  70        } else {
  71                eth_hdr->ether_type = rte_cpu_to_be_16(ether_type);
  72        }
  73}
  74
  75void
  76initialize_arp_header(struct rte_arp_hdr *arp_hdr,
  77                struct rte_ether_addr *src_mac,
  78                struct rte_ether_addr *dst_mac,
  79                uint32_t src_ip, uint32_t dst_ip,
  80                uint32_t opcode)
  81{
  82        arp_hdr->arp_hardware = rte_cpu_to_be_16(RTE_ARP_HRD_ETHER);
  83        arp_hdr->arp_protocol = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
  84        arp_hdr->arp_hlen = RTE_ETHER_ADDR_LEN;
  85        arp_hdr->arp_plen = sizeof(uint32_t);
  86        arp_hdr->arp_opcode = rte_cpu_to_be_16(opcode);
  87        rte_ether_addr_copy(src_mac, &arp_hdr->arp_data.arp_sha);
  88        arp_hdr->arp_data.arp_sip = src_ip;
  89        rte_ether_addr_copy(dst_mac, &arp_hdr->arp_data.arp_tha);
  90        arp_hdr->arp_data.arp_tip = dst_ip;
  91}
  92
  93uint16_t
  94initialize_udp_header(struct rte_udp_hdr *udp_hdr, uint16_t src_port,
  95                uint16_t dst_port, uint16_t pkt_data_len)
  96{
  97        uint16_t pkt_len;
  98
  99        pkt_len = (uint16_t) (pkt_data_len + sizeof(struct rte_udp_hdr));
 100
 101        udp_hdr->src_port = rte_cpu_to_be_16(src_port);
 102        udp_hdr->dst_port = rte_cpu_to_be_16(dst_port);
 103        udp_hdr->dgram_len = rte_cpu_to_be_16(pkt_len);
 104        udp_hdr->dgram_cksum = 0; /* No UDP checksum. */
 105
 106        return pkt_len;
 107}
 108
 109uint16_t
 110initialize_tcp_header(struct rte_tcp_hdr *tcp_hdr, uint16_t src_port,
 111                uint16_t dst_port, uint16_t pkt_data_len)
 112{
 113        uint16_t pkt_len;
 114
 115        pkt_len = (uint16_t) (pkt_data_len + sizeof(struct rte_tcp_hdr));
 116
 117        memset(tcp_hdr, 0, sizeof(struct rte_tcp_hdr));
 118        tcp_hdr->src_port = rte_cpu_to_be_16(src_port);
 119        tcp_hdr->dst_port = rte_cpu_to_be_16(dst_port);
 120        tcp_hdr->data_off = (sizeof(struct rte_tcp_hdr) << 2) & 0xF0;
 121
 122        return pkt_len;
 123}
 124
 125uint16_t
 126initialize_sctp_header(struct rte_sctp_hdr *sctp_hdr, uint16_t src_port,
 127                uint16_t dst_port, uint16_t pkt_data_len)
 128{
 129        uint16_t pkt_len;
 130
 131        pkt_len = (uint16_t) (pkt_data_len + sizeof(struct rte_udp_hdr));
 132
 133        sctp_hdr->src_port = rte_cpu_to_be_16(src_port);
 134        sctp_hdr->dst_port = rte_cpu_to_be_16(dst_port);
 135        sctp_hdr->tag = 0;
 136        sctp_hdr->cksum = 0; /* No SCTP checksum. */
 137
 138        return pkt_len;
 139}
 140
 141uint16_t
 142initialize_ipv6_header(struct rte_ipv6_hdr *ip_hdr, uint8_t *src_addr,
 143                uint8_t *dst_addr, uint16_t pkt_data_len)
 144{
 145        ip_hdr->vtc_flow = rte_cpu_to_be_32(0x60000000); /* Set version to 6. */
 146        ip_hdr->payload_len = rte_cpu_to_be_16(pkt_data_len);
 147        ip_hdr->proto = IPPROTO_UDP;
 148        ip_hdr->hop_limits = IP_DEFTTL;
 149
 150        rte_memcpy(ip_hdr->src_addr, src_addr, sizeof(ip_hdr->src_addr));
 151        rte_memcpy(ip_hdr->dst_addr, dst_addr, sizeof(ip_hdr->dst_addr));
 152
 153        return (uint16_t) (pkt_data_len + sizeof(struct rte_ipv6_hdr));
 154}
 155
 156uint16_t
 157initialize_ipv4_header(struct rte_ipv4_hdr *ip_hdr, uint32_t src_addr,
 158                uint32_t dst_addr, uint16_t pkt_data_len)
 159{
 160        uint16_t pkt_len;
 161        unaligned_uint16_t *ptr16;
 162        uint32_t ip_cksum;
 163
 164        /*
 165         * Initialize IP header.
 166         */
 167        pkt_len = (uint16_t) (pkt_data_len + sizeof(struct rte_ipv4_hdr));
 168
 169        ip_hdr->version_ihl   = RTE_IPV4_VHL_DEF;
 170        ip_hdr->type_of_service   = 0;
 171        ip_hdr->fragment_offset = 0;
 172        ip_hdr->time_to_live   = IP_DEFTTL;
 173        ip_hdr->next_proto_id = IPPROTO_UDP;
 174        ip_hdr->packet_id = 0;
 175        ip_hdr->total_length   = rte_cpu_to_be_16(pkt_len);
 176        ip_hdr->src_addr = rte_cpu_to_be_32(src_addr);
 177        ip_hdr->dst_addr = rte_cpu_to_be_32(dst_addr);
 178
 179        /*
 180         * Compute IP header checksum.
 181         */
 182        ptr16 = (unaligned_uint16_t *)ip_hdr;
 183        ip_cksum = 0;
 184        ip_cksum += ptr16[0]; ip_cksum += ptr16[1];
 185        ip_cksum += ptr16[2]; ip_cksum += ptr16[3];
 186        ip_cksum += ptr16[4];
 187        ip_cksum += ptr16[6]; ip_cksum += ptr16[7];
 188        ip_cksum += ptr16[8]; ip_cksum += ptr16[9];
 189
 190        /*
 191         * Reduce 32 bit checksum to 16 bits and complement it.
 192         */
 193        ip_cksum = ((ip_cksum & 0xFFFF0000) >> 16) +
 194                (ip_cksum & 0x0000FFFF);
 195        ip_cksum %= 65536;
 196        ip_cksum = (~ip_cksum) & 0x0000FFFF;
 197        if (ip_cksum == 0)
 198                ip_cksum = 0xFFFF;
 199        ip_hdr->hdr_checksum = (uint16_t) ip_cksum;
 200
 201        return pkt_len;
 202}
 203
 204uint16_t
 205initialize_ipv4_header_proto(struct rte_ipv4_hdr *ip_hdr, uint32_t src_addr,
 206                uint32_t dst_addr, uint16_t pkt_data_len, uint8_t proto)
 207{
 208        uint16_t pkt_len;
 209        unaligned_uint16_t *ptr16;
 210        uint32_t ip_cksum;
 211
 212        /*
 213         * Initialize IP header.
 214         */
 215        pkt_len = (uint16_t) (pkt_data_len + sizeof(struct rte_ipv4_hdr));
 216
 217        ip_hdr->version_ihl   = RTE_IPV4_VHL_DEF;
 218        ip_hdr->type_of_service   = 0;
 219        ip_hdr->fragment_offset = 0;
 220        ip_hdr->time_to_live   = IP_DEFTTL;
 221        ip_hdr->next_proto_id = proto;
 222        ip_hdr->packet_id = 0;
 223        ip_hdr->total_length   = rte_cpu_to_be_16(pkt_len);
 224        ip_hdr->src_addr = rte_cpu_to_be_32(src_addr);
 225        ip_hdr->dst_addr = rte_cpu_to_be_32(dst_addr);
 226
 227        /*
 228         * Compute IP header checksum.
 229         */
 230        ptr16 = (unaligned_uint16_t *)ip_hdr;
 231        ip_cksum = 0;
 232        ip_cksum += ptr16[0]; ip_cksum += ptr16[1];
 233        ip_cksum += ptr16[2]; ip_cksum += ptr16[3];
 234        ip_cksum += ptr16[4];
 235        ip_cksum += ptr16[6]; ip_cksum += ptr16[7];
 236        ip_cksum += ptr16[8]; ip_cksum += ptr16[9];
 237
 238        /*
 239         * Reduce 32 bit checksum to 16 bits and complement it.
 240         */
 241        ip_cksum = ((ip_cksum & 0xFFFF0000) >> 16) +
 242                (ip_cksum & 0x0000FFFF);
 243        ip_cksum %= 65536;
 244        ip_cksum = (~ip_cksum) & 0x0000FFFF;
 245        if (ip_cksum == 0)
 246                ip_cksum = 0xFFFF;
 247        ip_hdr->hdr_checksum = (uint16_t) ip_cksum;
 248
 249        return pkt_len;
 250}
 251
 252/*
 253 * The maximum number of segments per packet is used when creating
 254 * scattered transmit packets composed of a list of mbufs.
 255 */
 256#define RTE_MAX_SEGS_PER_PKT 255 /**< pkt.nb_segs is a 8-bit unsigned char. */
 257
 258
 259int
 260generate_packet_burst(struct rte_mempool *mp, struct rte_mbuf **pkts_burst,
 261                struct rte_ether_hdr *eth_hdr, uint8_t vlan_enabled,
 262                void *ip_hdr, uint8_t ipv4, struct rte_udp_hdr *udp_hdr,
 263                int nb_pkt_per_burst, uint8_t pkt_len, uint8_t nb_pkt_segs)
 264{
 265        int i, nb_pkt = 0;
 266        size_t eth_hdr_size;
 267
 268        struct rte_mbuf *pkt_seg;
 269        struct rte_mbuf *pkt;
 270
 271        for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) {
 272                pkt = rte_pktmbuf_alloc(mp);
 273                if (pkt == NULL) {
 274nomore_mbuf:
 275                        if (nb_pkt == 0)
 276                                return -1;
 277                        break;
 278                }
 279
 280                pkt->data_len = pkt_len;
 281                pkt_seg = pkt;
 282                for (i = 1; i < nb_pkt_segs; i++) {
 283                        pkt_seg->next = rte_pktmbuf_alloc(mp);
 284                        if (pkt_seg->next == NULL) {
 285                                pkt->nb_segs = i;
 286                                rte_pktmbuf_free(pkt);
 287                                goto nomore_mbuf;
 288                        }
 289                        pkt_seg = pkt_seg->next;
 290                        pkt_seg->data_len = pkt_len;
 291                }
 292                pkt_seg->next = NULL; /* Last segment of packet. */
 293
 294                /*
 295                 * Copy headers in first packet segment(s).
 296                 */
 297                if (vlan_enabled)
 298                        eth_hdr_size = sizeof(struct rte_ether_hdr) +
 299                                sizeof(struct rte_vlan_hdr);
 300                else
 301                        eth_hdr_size = sizeof(struct rte_ether_hdr);
 302
 303                copy_buf_to_pkt(eth_hdr, eth_hdr_size, pkt, 0);
 304
 305                if (ipv4) {
 306                        copy_buf_to_pkt(ip_hdr, sizeof(struct rte_ipv4_hdr),
 307                                pkt, eth_hdr_size);
 308                        copy_buf_to_pkt(udp_hdr, sizeof(*udp_hdr), pkt,
 309                                eth_hdr_size + sizeof(struct rte_ipv4_hdr));
 310                } else {
 311                        copy_buf_to_pkt(ip_hdr, sizeof(struct rte_ipv6_hdr),
 312                                pkt, eth_hdr_size);
 313                        copy_buf_to_pkt(udp_hdr, sizeof(*udp_hdr), pkt,
 314                                eth_hdr_size + sizeof(struct rte_ipv6_hdr));
 315                }
 316
 317                /*
 318                 * Complete first mbuf of packet and append it to the
 319                 * burst of packets to be transmitted.
 320                 */
 321                pkt->nb_segs = nb_pkt_segs;
 322                pkt->pkt_len = pkt_len;
 323                pkt->l2_len = eth_hdr_size;
 324
 325                if (ipv4) {
 326                        pkt->vlan_tci  = RTE_ETHER_TYPE_IPV4;
 327                        pkt->l3_len = sizeof(struct rte_ipv4_hdr);
 328                } else {
 329                        pkt->vlan_tci  = RTE_ETHER_TYPE_IPV6;
 330                        pkt->l3_len = sizeof(struct rte_ipv6_hdr);
 331                }
 332
 333                pkts_burst[nb_pkt] = pkt;
 334        }
 335
 336        return nb_pkt;
 337}
 338
 339int
 340generate_packet_burst_proto(struct rte_mempool *mp,
 341                struct rte_mbuf **pkts_burst, struct rte_ether_hdr *eth_hdr,
 342                uint8_t vlan_enabled, void *ip_hdr,
 343                uint8_t ipv4, uint8_t proto, void *proto_hdr,
 344                int nb_pkt_per_burst, uint8_t pkt_len, uint8_t nb_pkt_segs)
 345{
 346        int i, nb_pkt = 0;
 347        size_t eth_hdr_size;
 348
 349        struct rte_mbuf *pkt_seg;
 350        struct rte_mbuf *pkt;
 351
 352        for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) {
 353                pkt = rte_pktmbuf_alloc(mp);
 354                if (pkt == NULL) {
 355nomore_mbuf:
 356                        if (nb_pkt == 0)
 357                                return -1;
 358                        break;
 359                }
 360
 361                pkt->data_len = pkt_len;
 362                pkt_seg = pkt;
 363                for (i = 1; i < nb_pkt_segs; i++) {
 364                        pkt_seg->next = rte_pktmbuf_alloc(mp);
 365                        if (pkt_seg->next == NULL) {
 366                                pkt->nb_segs = i;
 367                                rte_pktmbuf_free(pkt);
 368                                goto nomore_mbuf;
 369                        }
 370                        pkt_seg = pkt_seg->next;
 371                        pkt_seg->data_len = pkt_len;
 372                }
 373                pkt_seg->next = NULL; /* Last segment of packet. */
 374
 375                /*
 376                 * Copy headers in first packet segment(s).
 377                 */
 378                if (vlan_enabled)
 379                        eth_hdr_size = sizeof(struct rte_ether_hdr) +
 380                                sizeof(struct rte_vlan_hdr);
 381                else
 382                        eth_hdr_size = sizeof(struct rte_ether_hdr);
 383
 384                copy_buf_to_pkt(eth_hdr, eth_hdr_size, pkt, 0);
 385
 386                if (ipv4) {
 387                        copy_buf_to_pkt(ip_hdr, sizeof(struct rte_ipv4_hdr),
 388                                        pkt, eth_hdr_size);
 389                        switch (proto) {
 390                        case IPPROTO_UDP:
 391                                copy_buf_to_pkt(proto_hdr,
 392                                        sizeof(struct rte_udp_hdr), pkt,
 393                                        eth_hdr_size +
 394                                                sizeof(struct rte_ipv4_hdr));
 395                                break;
 396                        case IPPROTO_TCP:
 397                                copy_buf_to_pkt(proto_hdr,
 398                                        sizeof(struct rte_tcp_hdr), pkt,
 399                                        eth_hdr_size +
 400                                                sizeof(struct rte_ipv4_hdr));
 401                                break;
 402                        case IPPROTO_SCTP:
 403                                copy_buf_to_pkt(proto_hdr,
 404                                        sizeof(struct rte_sctp_hdr), pkt,
 405                                        eth_hdr_size +
 406                                                sizeof(struct rte_ipv4_hdr));
 407                                break;
 408                        default:
 409                                break;
 410                        }
 411                } else {
 412                        copy_buf_to_pkt(ip_hdr, sizeof(struct rte_ipv6_hdr),
 413                                        pkt, eth_hdr_size);
 414                        switch (proto) {
 415                        case IPPROTO_UDP:
 416                                copy_buf_to_pkt(proto_hdr,
 417                                        sizeof(struct rte_udp_hdr), pkt,
 418                                        eth_hdr_size +
 419                                                sizeof(struct rte_ipv6_hdr));
 420                                break;
 421                        case IPPROTO_TCP:
 422                                copy_buf_to_pkt(proto_hdr,
 423                                        sizeof(struct rte_tcp_hdr), pkt,
 424                                        eth_hdr_size +
 425                                                sizeof(struct rte_ipv6_hdr));
 426                                break;
 427                        case IPPROTO_SCTP:
 428                                copy_buf_to_pkt(proto_hdr,
 429                                        sizeof(struct rte_sctp_hdr), pkt,
 430                                        eth_hdr_size +
 431                                                sizeof(struct rte_ipv6_hdr));
 432                                break;
 433                        default:
 434                                break;
 435                        }
 436                }
 437
 438                /*
 439                 * Complete first mbuf of packet and append it to the
 440                 * burst of packets to be transmitted.
 441                 */
 442                pkt->nb_segs = nb_pkt_segs;
 443                pkt->pkt_len = pkt_len;
 444                pkt->l2_len = eth_hdr_size;
 445
 446                if (ipv4) {
 447                        pkt->vlan_tci  = RTE_ETHER_TYPE_IPV4;
 448                        pkt->l3_len = sizeof(struct rte_ipv4_hdr);
 449                } else {
 450                        pkt->vlan_tci  = RTE_ETHER_TYPE_IPV6;
 451                        pkt->l3_len = sizeof(struct rte_ipv6_hdr);
 452                }
 453
 454                pkts_burst[nb_pkt] = pkt;
 455        }
 456
 457        return nb_pkt;
 458}
 459