net: add rte prefix to SCTP structure
[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 rte_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 rte_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 rte_ipv6_hdr));
155 }
156
157 uint16_t
158 initialize_ipv4_header(struct rte_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 rte_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 rte_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 rte_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 rte_ipv4_hdr),
308                                 pkt, eth_hdr_size);
309                         copy_buf_to_pkt(udp_hdr, sizeof(*udp_hdr), pkt,
310                                 eth_hdr_size + sizeof(struct rte_ipv4_hdr));
311                 } else {
312                         copy_buf_to_pkt(ip_hdr, sizeof(struct rte_ipv6_hdr),
313                                 pkt, eth_hdr_size);
314                         copy_buf_to_pkt(udp_hdr, sizeof(*udp_hdr), pkt,
315                                 eth_hdr_size + sizeof(struct rte_ipv6_hdr));
316                 }
317
318                 /*
319                  * Complete first mbuf of packet and append it to the
320                  * burst of packets to be transmitted.
321                  */
322                 pkt->nb_segs = nb_pkt_segs;
323                 pkt->pkt_len = pkt_len;
324                 pkt->l2_len = eth_hdr_size;
325
326                 if (ipv4) {
327                         pkt->vlan_tci  = RTE_ETHER_TYPE_IPv4;
328                         pkt->l3_len = sizeof(struct rte_ipv4_hdr);
329                 } else {
330                         pkt->vlan_tci  = RTE_ETHER_TYPE_IPv6;
331                         pkt->l3_len = sizeof(struct rte_ipv6_hdr);
332                 }
333
334                 pkts_burst[nb_pkt] = pkt;
335         }
336
337         return nb_pkt;
338 }
339
340 int
341 generate_packet_burst_proto(struct rte_mempool *mp,
342                 struct rte_mbuf **pkts_burst, struct rte_ether_hdr *eth_hdr,
343                 uint8_t vlan_enabled, void *ip_hdr,
344                 uint8_t ipv4, uint8_t proto, void *proto_hdr,
345                 int nb_pkt_per_burst, uint8_t pkt_len, uint8_t nb_pkt_segs)
346 {
347         int i, nb_pkt = 0;
348         size_t eth_hdr_size;
349
350         struct rte_mbuf *pkt_seg;
351         struct rte_mbuf *pkt;
352
353         for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) {
354                 pkt = rte_pktmbuf_alloc(mp);
355                 if (pkt == NULL) {
356 nomore_mbuf:
357                         if (nb_pkt == 0)
358                                 return -1;
359                         break;
360                 }
361
362                 pkt->data_len = pkt_len;
363                 pkt_seg = pkt;
364                 for (i = 1; i < nb_pkt_segs; i++) {
365                         pkt_seg->next = rte_pktmbuf_alloc(mp);
366                         if (pkt_seg->next == NULL) {
367                                 pkt->nb_segs = i;
368                                 rte_pktmbuf_free(pkt);
369                                 goto nomore_mbuf;
370                         }
371                         pkt_seg = pkt_seg->next;
372                         pkt_seg->data_len = pkt_len;
373                 }
374                 pkt_seg->next = NULL; /* Last segment of packet. */
375
376                 /*
377                  * Copy headers in first packet segment(s).
378                  */
379                 if (vlan_enabled)
380                         eth_hdr_size = sizeof(struct rte_ether_hdr) +
381                                 sizeof(struct rte_vlan_hdr);
382                 else
383                         eth_hdr_size = sizeof(struct rte_ether_hdr);
384
385                 copy_buf_to_pkt(eth_hdr, eth_hdr_size, pkt, 0);
386
387                 if (ipv4) {
388                         copy_buf_to_pkt(ip_hdr, sizeof(struct rte_ipv4_hdr),
389                                         pkt, eth_hdr_size);
390                         switch (proto) {
391                         case IPPROTO_UDP:
392                                 copy_buf_to_pkt(proto_hdr,
393                                         sizeof(struct udp_hdr), pkt,
394                                         eth_hdr_size +
395                                                 sizeof(struct rte_ipv4_hdr));
396                                 break;
397                         case IPPROTO_TCP:
398                                 copy_buf_to_pkt(proto_hdr,
399                                         sizeof(struct tcp_hdr), pkt,
400                                         eth_hdr_size +
401                                                 sizeof(struct rte_ipv4_hdr));
402                                 break;
403                         case IPPROTO_SCTP:
404                                 copy_buf_to_pkt(proto_hdr,
405                                         sizeof(struct rte_sctp_hdr), pkt,
406                                         eth_hdr_size +
407                                                 sizeof(struct rte_ipv4_hdr));
408                                 break;
409                         default:
410                                 break;
411                         }
412                 } else {
413                         copy_buf_to_pkt(ip_hdr, sizeof(struct rte_ipv6_hdr),
414                                         pkt, eth_hdr_size);
415                         switch (proto) {
416                         case IPPROTO_UDP:
417                                 copy_buf_to_pkt(proto_hdr,
418                                         sizeof(struct udp_hdr), pkt,
419                                         eth_hdr_size +
420                                                 sizeof(struct rte_ipv6_hdr));
421                                 break;
422                         case IPPROTO_TCP:
423                                 copy_buf_to_pkt(proto_hdr,
424                                         sizeof(struct tcp_hdr), pkt,
425                                         eth_hdr_size +
426                                                 sizeof(struct rte_ipv6_hdr));
427                                 break;
428                         case IPPROTO_SCTP:
429                                 copy_buf_to_pkt(proto_hdr,
430                                         sizeof(struct rte_sctp_hdr), pkt,
431                                         eth_hdr_size +
432                                                 sizeof(struct rte_ipv6_hdr));
433                                 break;
434                         default:
435                                 break;
436                         }
437                 }
438
439                 /*
440                  * Complete first mbuf of packet and append it to the
441                  * burst of packets to be transmitted.
442                  */
443                 pkt->nb_segs = nb_pkt_segs;
444                 pkt->pkt_len = pkt_len;
445                 pkt->l2_len = eth_hdr_size;
446
447                 if (ipv4) {
448                         pkt->vlan_tci  = RTE_ETHER_TYPE_IPv4;
449                         pkt->l3_len = sizeof(struct rte_ipv4_hdr);
450                 } else {
451                         pkt->vlan_tci  = RTE_ETHER_TYPE_IPv6;
452                         pkt->l3_len = sizeof(struct rte_ipv6_hdr);
453                 }
454
455                 pkts_burst[nb_pkt] = pkt;
456         }
457
458         return nb_pkt;
459 }