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