uint32_t cls_pkt_get_seq(odp_packet_t pkt) { uint32_t offset; cls_test_packet_t data; odph_ipv4hdr_t *ip; odph_tcphdr_t *tcp; ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); offset = odp_packet_l4_offset(pkt); if (!offset && !ip) return TEST_SEQ_INVALID; if (ip->proto == ODPH_IPPROTO_UDP) odp_packet_copydata_out(pkt, offset + ODPH_UDPHDR_LEN, sizeof(data), &data); else { tcp = (odph_tcphdr_t *)odp_packet_l4_ptr(pkt, NULL); odp_packet_copydata_out(pkt, offset + tcp->hl * 4, sizeof(data), &data); } if (data.magic == DATA_MAGIC) return data.seq; return TEST_SEQ_INVALID; }
static uint32_t pktio_pkt_seq(odp_packet_t pkt) { size_t off; uint32_t seq = TEST_SEQ_INVALID; pkt_head_t head; pkt_tail_t tail; if (pkt == ODP_PACKET_INVALID) return TEST_SEQ_INVALID; off = odp_packet_l4_offset(pkt); if (off == ODP_PACKET_OFFSET_INVALID) return TEST_SEQ_INVALID; off += ODPH_UDPHDR_LEN; if (odp_packet_copydata_out(pkt, off, sizeof(head), &head) != 0) return TEST_SEQ_INVALID; if (head.magic != TEST_SEQ_MAGIC) return TEST_SEQ_INVALID; if (odp_packet_len(pkt) == packet_len) { off = packet_len - sizeof(tail); if (odp_packet_copydata_out(pkt, off, sizeof(tail), &tail) != 0) return TEST_SEQ_INVALID; if (tail.magic == TEST_SEQ_MAGIC) { seq = head.seq; CU_ASSERT(seq != TEST_SEQ_INVALID); } } return seq; }
static uint32_t cls_pkt_get_seq(odp_packet_t pkt) { uint32_t offset; cls_test_packet_t data; offset = odp_packet_l4_offset(pkt); if (offset) { odp_packet_copydata_out(pkt, offset + ODPH_UDPHDR_LEN, sizeof(data), &data); if (data.magic == DATA_MAGIC) return data.seq; } return TEST_SEQ_INVALID; }
/* * Check if a packet payload contains test payload magic number. */ static int pktio_pkt_has_magic(odp_packet_t pkt) { size_t l4_off; pkt_head_t pkt_hdr; l4_off = odp_packet_l4_offset(pkt); if (l4_off) { int ret = odp_packet_copydata_out(pkt, l4_off+ODPH_UDPHDR_LEN, sizeof(pkt_hdr), &pkt_hdr); if (ret != 0) return 0; if (pkt_hdr.magic == TEST_HDR_MAGIC) return 1; } return 0; }
static inline unsigned pkt_mmap_v2_tx(int sock, struct ring *ring, odp_packet_t pkt_table[], unsigned len) { union frame_map ppd; uint32_t pkt_len; unsigned first_frame_num, frame_num, frame_count; int ret; uint8_t *buf; unsigned n, i = 0; unsigned nb_tx = 0; int send_errno; int total_len = 0; first_frame_num = ring->frame_num; frame_num = first_frame_num; frame_count = ring->rd_num; while (i < len) { ppd.raw = ring->rd[frame_num].iov_base; if (!odp_unlikely(mmap_tx_kernel_ready(ppd.raw))) break; pkt_len = odp_packet_len(pkt_table[i]); ppd.v2->tp_h.tp_snaplen = pkt_len; ppd.v2->tp_h.tp_len = pkt_len; total_len += pkt_len; buf = (uint8_t *)ppd.raw + TPACKET2_HDRLEN - sizeof(struct sockaddr_ll); odp_packet_copydata_out(pkt_table[i], 0, pkt_len, buf); mmap_tx_user_ready(ppd.raw); if (++frame_num >= frame_count) frame_num = 0; i++; } ret = sendto(sock, NULL, 0, MSG_DONTWAIT, NULL, 0); send_errno = errno; /* On success, the return value indicates the number of bytes sent. On * failure a value of -1 is returned, even if the failure occurred * after some of the packets in the ring have already been sent, so we * need to inspect the packet status to determine which were sent. */ if (odp_likely(ret == total_len)) { nb_tx = i; ring->frame_num = frame_num; } else if (ret == -1) { for (frame_num = first_frame_num, n = 0; n < i; ++n) { struct tpacket2_hdr *hdr = ring->rd[frame_num].iov_base; if (odp_likely(hdr->tp_status == TP_STATUS_AVAILABLE || hdr->tp_status == TP_STATUS_SENDING)) { nb_tx++; } else { /* The remaining frames weren't sent, clear * their status to indicate we're not waiting * for the kernel to process them. */ hdr->tp_status = TP_STATUS_AVAILABLE; } if (++frame_num >= frame_count) frame_num = 0; } ring->frame_num = (first_frame_num + nb_tx) % frame_count; if (nb_tx == 0 && SOCK_ERR_REPORT(send_errno)) { __odp_errno = send_errno; /* ENOBUFS indicates that the transmit queue is full, * which will happen regularly when overloaded so don't * print it */ if (errno != ENOBUFS) ODP_ERR("sendto(pkt mmap): %s\n", strerror(send_errno)); return -1; } } else { /* Short send, return value is number of bytes sent so use this * to determine number of complete frames sent. */ for (n = 0; n < i && ret > 0; ++n) { ret -= odp_packet_len(pkt_table[n]); if (ret >= 0) nb_tx++; } ring->frame_num = (first_frame_num + nb_tx) % frame_count; } for (i = 0; i < nb_tx; ++i) odp_packet_free(pkt_table[i]); return nb_tx; }
static enum ofp_return_code ofp_fragment_pkt(odp_packet_t pkt, struct ofp_ifnet *dev_out, uint8_t is_local_address) { struct ofp_ip *ip, *ip_new; uint16_t vlan = dev_out->vlan; int tot_len, pl_len, seg_len, pl_pos, flen, hwlen; uint16_t frag, frag_new; uint8_t *payload_new; uint32_t payload_offset; odp_pool_t pkt_pool; odp_packet_t pkt_new; struct ofp_ether_header *eth, *eth_new; struct ofp_ether_vlan_header *eth_vlan, *eth_new_vlan; int ret = OFP_PKT_PROCESSED; if (!vlan) eth = odp_packet_l2_ptr(pkt, NULL); else eth_vlan = odp_packet_l2_ptr(pkt, NULL); ip = (struct ofp_ip *)odp_packet_l3_ptr(pkt, NULL); pkt_pool = ofp_packet_pool; tot_len = odp_be_to_cpu_16(ip->ip_len); pl_len = tot_len - (ip->ip_hl<<2); seg_len = (dev_out->if_mtu - sizeof(struct ofp_ip)) & 0xfff8; pl_pos = 0; frag = odp_be_to_cpu_16(ip->ip_off); payload_offset = odp_packet_l3_offset(pkt) + (ip->ip_hl<<2); OFP_UPDATE_PACKET_STAT(tx_eth_frag, 1); while (pl_pos < pl_len) { flen = (pl_len - pl_pos) > seg_len ? seg_len : (pl_len - pl_pos); hwlen = flen + sizeof(struct ofp_ip) + (vlan ? sizeof(struct ofp_ether_vlan_header) : sizeof(struct ofp_ether_header)); pkt_new = odp_packet_alloc(pkt_pool, hwlen); if (pkt_new == ODP_PACKET_INVALID) { OFP_ERR("odp_packet_alloc failed"); return OFP_PKT_DROP; } odp_packet_user_ptr_set(pkt_new, odp_packet_user_ptr(pkt)); odp_packet_l2_offset_set(pkt_new, 0); if (vlan) { eth_new_vlan = odp_packet_l2_ptr(pkt_new, NULL); *eth_new_vlan = *eth_vlan; ip_new = (struct ofp_ip *)(eth_new_vlan + 1); odp_packet_l3_offset_set(pkt_new, OFP_ETHER_HDR_LEN + OFP_ETHER_VLAN_ENCAP_LEN); } else { eth_new = odp_packet_l2_ptr(pkt_new, NULL); *eth_new = *eth; ip_new = (struct ofp_ip *)(eth_new + 1); odp_packet_l3_offset_set(pkt_new, OFP_ETHER_HDR_LEN); } *ip_new = *ip; payload_new = (uint8_t *)(ip_new + 1); if (odp_packet_copydata_out(pkt, payload_offset + pl_pos, flen, payload_new) < 0) { OFP_ERR("odp_packet_copydata_out failed"); return OFP_PKT_DROP; }; ip_new->ip_len = odp_cpu_to_be_16(flen + sizeof(*ip_new)); frag_new = frag + pl_pos/8; pl_pos += flen; if (pl_pos < pl_len) frag_new |= OFP_IP_MF; ip_new->ip_off = odp_cpu_to_be_16(frag_new); ip_new->ip_sum = 0; ip_new->ip_sum = ofp_cksum_buffer((uint16_t *)ip_new, sizeof(*ip_new)); if (is_local_address) ret = send_pkt_loop(dev_out, pkt_new); else ret = send_pkt_out(dev_out, pkt_new); if (ret == OFP_PKT_DROP) { odp_packet_free(pkt_new); return OFP_PKT_DROP; } } odp_packet_free(pkt); return OFP_PKT_PROCESSED; }