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