]>
git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/dpdk/app/test/packet_burst_generator.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
5 #include <rte_byteorder.h>
8 #include "packet_burst_generator.h"
10 #define UDP_SRC_PORT 1024
11 #define UDP_DST_PORT 1024
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)
20 copy_buf_to_pkt_segs(void *buf
, unsigned len
, struct rte_mbuf
*pkt
,
28 while (offset
>= seg
->data_len
) {
29 offset
-= seg
->data_len
;
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
);
37 buf
= ((char *) buf
+ copy_len
);
39 seg_buf
= rte_pktmbuf_mtod(seg
, void *);
41 rte_memcpy(seg_buf
, buf
, (size_t) len
);
45 copy_buf_to_pkt(void *buf
, unsigned len
, struct rte_mbuf
*pkt
, unsigned offset
)
47 if (offset
+ len
<= pkt
->data_len
) {
48 rte_memcpy(rte_pktmbuf_mtod_offset(pkt
, char *, offset
), buf
,
52 copy_buf_to_pkt_segs(buf
, len
, pkt
, offset
);
56 initialize_eth_header(struct ether_hdr
*eth_hdr
, struct ether_addr
*src_mac
,
57 struct ether_addr
*dst_mac
, uint16_t ether_type
,
58 uint8_t vlan_enabled
, uint16_t van_id
)
60 ether_addr_copy(dst_mac
, ð_hdr
->d_addr
);
61 ether_addr_copy(src_mac
, ð_hdr
->s_addr
);
64 struct vlan_hdr
*vhdr
= (struct vlan_hdr
*)((uint8_t *)eth_hdr
+
65 sizeof(struct ether_hdr
));
67 eth_hdr
->ether_type
= rte_cpu_to_be_16(ETHER_TYPE_VLAN
);
69 vhdr
->eth_proto
= rte_cpu_to_be_16(ether_type
);
70 vhdr
->vlan_tci
= van_id
;
72 eth_hdr
->ether_type
= rte_cpu_to_be_16(ether_type
);
77 initialize_arp_header(struct arp_hdr
*arp_hdr
, struct ether_addr
*src_mac
,
78 struct ether_addr
*dst_mac
, uint32_t src_ip
, uint32_t dst_ip
,
81 arp_hdr
->arp_hrd
= rte_cpu_to_be_16(ARP_HRD_ETHER
);
82 arp_hdr
->arp_pro
= rte_cpu_to_be_16(ETHER_TYPE_IPv4
);
83 arp_hdr
->arp_hln
= ETHER_ADDR_LEN
;
84 arp_hdr
->arp_pln
= sizeof(uint32_t);
85 arp_hdr
->arp_op
= rte_cpu_to_be_16(opcode
);
86 ether_addr_copy(src_mac
, &arp_hdr
->arp_data
.arp_sha
);
87 arp_hdr
->arp_data
.arp_sip
= src_ip
;
88 ether_addr_copy(dst_mac
, &arp_hdr
->arp_data
.arp_tha
);
89 arp_hdr
->arp_data
.arp_tip
= dst_ip
;
93 initialize_udp_header(struct udp_hdr
*udp_hdr
, uint16_t src_port
,
94 uint16_t dst_port
, uint16_t pkt_data_len
)
98 pkt_len
= (uint16_t) (pkt_data_len
+ sizeof(struct udp_hdr
));
100 udp_hdr
->src_port
= rte_cpu_to_be_16(src_port
);
101 udp_hdr
->dst_port
= rte_cpu_to_be_16(dst_port
);
102 udp_hdr
->dgram_len
= rte_cpu_to_be_16(pkt_len
);
103 udp_hdr
->dgram_cksum
= 0; /* No UDP checksum. */
109 initialize_tcp_header(struct tcp_hdr
*tcp_hdr
, uint16_t src_port
,
110 uint16_t dst_port
, uint16_t pkt_data_len
)
114 pkt_len
= (uint16_t) (pkt_data_len
+ sizeof(struct tcp_hdr
));
116 memset(tcp_hdr
, 0, sizeof(struct tcp_hdr
));
117 tcp_hdr
->src_port
= rte_cpu_to_be_16(src_port
);
118 tcp_hdr
->dst_port
= rte_cpu_to_be_16(dst_port
);
124 initialize_sctp_header(struct sctp_hdr
*sctp_hdr
, uint16_t src_port
,
125 uint16_t dst_port
, uint16_t pkt_data_len
)
129 pkt_len
= (uint16_t) (pkt_data_len
+ sizeof(struct udp_hdr
));
131 sctp_hdr
->src_port
= rte_cpu_to_be_16(src_port
);
132 sctp_hdr
->dst_port
= rte_cpu_to_be_16(dst_port
);
134 sctp_hdr
->cksum
= 0; /* No SCTP checksum. */
140 initialize_ipv6_header(struct ipv6_hdr
*ip_hdr
, uint8_t *src_addr
,
141 uint8_t *dst_addr
, uint16_t pkt_data_len
)
143 ip_hdr
->vtc_flow
= 0;
144 ip_hdr
->payload_len
= pkt_data_len
;
145 ip_hdr
->proto
= IPPROTO_UDP
;
146 ip_hdr
->hop_limits
= IP_DEFTTL
;
148 rte_memcpy(ip_hdr
->src_addr
, src_addr
, sizeof(ip_hdr
->src_addr
));
149 rte_memcpy(ip_hdr
->dst_addr
, dst_addr
, sizeof(ip_hdr
->dst_addr
));
151 return (uint16_t) (pkt_data_len
+ sizeof(struct ipv6_hdr
));
155 initialize_ipv4_header(struct ipv4_hdr
*ip_hdr
, uint32_t src_addr
,
156 uint32_t dst_addr
, uint16_t pkt_data_len
)
159 unaligned_uint16_t
*ptr16
;
163 * Initialize IP header.
165 pkt_len
= (uint16_t) (pkt_data_len
+ sizeof(struct ipv4_hdr
));
167 ip_hdr
->version_ihl
= IP_VHL_DEF
;
168 ip_hdr
->type_of_service
= 0;
169 ip_hdr
->fragment_offset
= 0;
170 ip_hdr
->time_to_live
= IP_DEFTTL
;
171 ip_hdr
->next_proto_id
= IPPROTO_UDP
;
172 ip_hdr
->packet_id
= 0;
173 ip_hdr
->total_length
= rte_cpu_to_be_16(pkt_len
);
174 ip_hdr
->src_addr
= rte_cpu_to_be_32(src_addr
);
175 ip_hdr
->dst_addr
= rte_cpu_to_be_32(dst_addr
);
178 * Compute IP header checksum.
180 ptr16
= (unaligned_uint16_t
*)ip_hdr
;
182 ip_cksum
+= ptr16
[0]; ip_cksum
+= ptr16
[1];
183 ip_cksum
+= ptr16
[2]; ip_cksum
+= ptr16
[3];
184 ip_cksum
+= ptr16
[4];
185 ip_cksum
+= ptr16
[6]; ip_cksum
+= ptr16
[7];
186 ip_cksum
+= ptr16
[8]; ip_cksum
+= ptr16
[9];
189 * Reduce 32 bit checksum to 16 bits and complement it.
191 ip_cksum
= ((ip_cksum
& 0xFFFF0000) >> 16) +
192 (ip_cksum
& 0x0000FFFF);
194 ip_cksum
= (~ip_cksum
) & 0x0000FFFF;
197 ip_hdr
->hdr_checksum
= (uint16_t) ip_cksum
;
203 initialize_ipv4_header_proto(struct ipv4_hdr
*ip_hdr
, uint32_t src_addr
,
204 uint32_t dst_addr
, uint16_t pkt_data_len
, uint8_t proto
)
207 unaligned_uint16_t
*ptr16
;
211 * Initialize IP header.
213 pkt_len
= (uint16_t) (pkt_data_len
+ sizeof(struct ipv4_hdr
));
215 ip_hdr
->version_ihl
= IP_VHL_DEF
;
216 ip_hdr
->type_of_service
= 0;
217 ip_hdr
->fragment_offset
= 0;
218 ip_hdr
->time_to_live
= IP_DEFTTL
;
219 ip_hdr
->next_proto_id
= proto
;
220 ip_hdr
->packet_id
= 0;
221 ip_hdr
->total_length
= rte_cpu_to_be_16(pkt_len
);
222 ip_hdr
->src_addr
= rte_cpu_to_be_32(src_addr
);
223 ip_hdr
->dst_addr
= rte_cpu_to_be_32(dst_addr
);
226 * Compute IP header checksum.
228 ptr16
= (unaligned_uint16_t
*)ip_hdr
;
230 ip_cksum
+= ptr16
[0]; ip_cksum
+= ptr16
[1];
231 ip_cksum
+= ptr16
[2]; ip_cksum
+= ptr16
[3];
232 ip_cksum
+= ptr16
[4];
233 ip_cksum
+= ptr16
[6]; ip_cksum
+= ptr16
[7];
234 ip_cksum
+= ptr16
[8]; ip_cksum
+= ptr16
[9];
237 * Reduce 32 bit checksum to 16 bits and complement it.
239 ip_cksum
= ((ip_cksum
& 0xFFFF0000) >> 16) +
240 (ip_cksum
& 0x0000FFFF);
242 ip_cksum
= (~ip_cksum
) & 0x0000FFFF;
245 ip_hdr
->hdr_checksum
= (uint16_t) ip_cksum
;
251 * The maximum number of segments per packet is used when creating
252 * scattered transmit packets composed of a list of mbufs.
254 #define RTE_MAX_SEGS_PER_PKT 255 /**< pkt.nb_segs is a 8-bit unsigned char. */
258 generate_packet_burst(struct rte_mempool
*mp
, struct rte_mbuf
**pkts_burst
,
259 struct ether_hdr
*eth_hdr
, uint8_t vlan_enabled
, void *ip_hdr
,
260 uint8_t ipv4
, struct udp_hdr
*udp_hdr
, int nb_pkt_per_burst
,
261 uint8_t pkt_len
, uint8_t nb_pkt_segs
)
266 struct rte_mbuf
*pkt_seg
;
267 struct rte_mbuf
*pkt
;
269 for (nb_pkt
= 0; nb_pkt
< nb_pkt_per_burst
; nb_pkt
++) {
270 pkt
= rte_pktmbuf_alloc(mp
);
278 pkt
->data_len
= pkt_len
;
280 for (i
= 1; i
< nb_pkt_segs
; i
++) {
281 pkt_seg
->next
= rte_pktmbuf_alloc(mp
);
282 if (pkt_seg
->next
== NULL
) {
284 rte_pktmbuf_free(pkt
);
287 pkt_seg
= pkt_seg
->next
;
288 pkt_seg
->data_len
= pkt_len
;
290 pkt_seg
->next
= NULL
; /* Last segment of packet. */
293 * Copy headers in first packet segment(s).
296 eth_hdr_size
= sizeof(struct ether_hdr
) + sizeof(struct vlan_hdr
);
298 eth_hdr_size
= sizeof(struct ether_hdr
);
300 copy_buf_to_pkt(eth_hdr
, eth_hdr_size
, pkt
, 0);
303 copy_buf_to_pkt(ip_hdr
, sizeof(struct ipv4_hdr
), pkt
, eth_hdr_size
);
304 copy_buf_to_pkt(udp_hdr
, sizeof(*udp_hdr
), pkt
, eth_hdr_size
+
305 sizeof(struct ipv4_hdr
));
307 copy_buf_to_pkt(ip_hdr
, sizeof(struct ipv6_hdr
), pkt
, eth_hdr_size
);
308 copy_buf_to_pkt(udp_hdr
, sizeof(*udp_hdr
), pkt
, eth_hdr_size
+
309 sizeof(struct ipv6_hdr
));
313 * Complete first mbuf of packet and append it to the
314 * burst of packets to be transmitted.
316 pkt
->nb_segs
= nb_pkt_segs
;
317 pkt
->pkt_len
= pkt_len
;
318 pkt
->l2_len
= eth_hdr_size
;
321 pkt
->vlan_tci
= ETHER_TYPE_IPv4
;
322 pkt
->l3_len
= sizeof(struct ipv4_hdr
);
324 pkt
->vlan_tci
= ETHER_TYPE_IPv6
;
325 pkt
->l3_len
= sizeof(struct ipv6_hdr
);
328 pkts_burst
[nb_pkt
] = pkt
;
335 generate_packet_burst_proto(struct rte_mempool
*mp
,
336 struct rte_mbuf
**pkts_burst
,
337 struct ether_hdr
*eth_hdr
, uint8_t vlan_enabled
, void *ip_hdr
,
338 uint8_t ipv4
, uint8_t proto
, void *proto_hdr
,
339 int nb_pkt_per_burst
, uint8_t pkt_len
, uint8_t nb_pkt_segs
)
344 struct rte_mbuf
*pkt_seg
;
345 struct rte_mbuf
*pkt
;
347 for (nb_pkt
= 0; nb_pkt
< nb_pkt_per_burst
; nb_pkt
++) {
348 pkt
= rte_pktmbuf_alloc(mp
);
356 pkt
->data_len
= pkt_len
;
358 for (i
= 1; i
< nb_pkt_segs
; i
++) {
359 pkt_seg
->next
= rte_pktmbuf_alloc(mp
);
360 if (pkt_seg
->next
== NULL
) {
362 rte_pktmbuf_free(pkt
);
365 pkt_seg
= pkt_seg
->next
;
366 pkt_seg
->data_len
= pkt_len
;
368 pkt_seg
->next
= NULL
; /* Last segment of packet. */
371 * Copy headers in first packet segment(s).
374 eth_hdr_size
= sizeof(struct ether_hdr
) +
375 sizeof(struct vlan_hdr
);
377 eth_hdr_size
= sizeof(struct ether_hdr
);
379 copy_buf_to_pkt(eth_hdr
, eth_hdr_size
, pkt
, 0);
382 copy_buf_to_pkt(ip_hdr
, sizeof(struct ipv4_hdr
), pkt
,
386 copy_buf_to_pkt(proto_hdr
,
387 sizeof(struct udp_hdr
), pkt
,
388 eth_hdr_size
+ sizeof(struct ipv4_hdr
));
391 copy_buf_to_pkt(proto_hdr
,
392 sizeof(struct tcp_hdr
), pkt
,
393 eth_hdr_size
+ sizeof(struct ipv4_hdr
));
396 copy_buf_to_pkt(proto_hdr
,
397 sizeof(struct sctp_hdr
), pkt
,
398 eth_hdr_size
+ sizeof(struct ipv4_hdr
));
404 copy_buf_to_pkt(ip_hdr
, sizeof(struct ipv6_hdr
), pkt
,
408 copy_buf_to_pkt(proto_hdr
,
409 sizeof(struct udp_hdr
), pkt
,
410 eth_hdr_size
+ sizeof(struct ipv6_hdr
));
413 copy_buf_to_pkt(proto_hdr
,
414 sizeof(struct tcp_hdr
), pkt
,
415 eth_hdr_size
+ sizeof(struct ipv6_hdr
));
418 copy_buf_to_pkt(proto_hdr
,
419 sizeof(struct sctp_hdr
), pkt
,
420 eth_hdr_size
+ sizeof(struct ipv6_hdr
));
428 * Complete first mbuf of packet and append it to the
429 * burst of packets to be transmitted.
431 pkt
->nb_segs
= nb_pkt_segs
;
432 pkt
->pkt_len
= pkt_len
;
433 pkt
->l2_len
= eth_hdr_size
;
436 pkt
->vlan_tci
= ETHER_TYPE_IPv4
;
437 pkt
->l3_len
= sizeof(struct ipv4_hdr
);
439 pkt
->vlan_tci
= ETHER_TYPE_IPv6
;
440 pkt
->l3_len
= sizeof(struct ipv6_hdr
);
443 pkts_burst
[nb_pkt
] = pkt
;