Fixes bug #1670 Signed-off-by: Nicolas Morey-Chaisemartin <nmo...@kalray.eu> --- platform/linux-generic/odp_packet_socket.c | 95 +++++++++++++++++++++++++----- 1 file changed, 79 insertions(+), 16 deletions(-)
diff --git a/platform/linux-generic/odp_packet_socket.c b/platform/linux-generic/odp_packet_socket.c index c0f7a55..ffaf6dd 100644 --- a/platform/linux-generic/odp_packet_socket.c +++ b/platform/linux-generic/odp_packet_socket.c @@ -137,7 +137,8 @@ int setup_pkt_sock(pkt_sock_t *const pkt_sock, const char *netdev, /* Store eth buffer offset for pkt buffers from this pool */ pkt_sock->frame_offset = 0; /* pkt buffer size */ - pkt_sock->buf_size = odp_buffer_pool_segment_size(pool); + pkt_sock->buf_size = ODP_BUFFER_MAX_SEG * + odp_buffer_pool_segment_size(pool); /* max frame len taking into account the l2-offset */ pkt_sock->max_frame_len = pkt_sock->buf_size - odp_buffer_pool_headroom(pool) - @@ -204,6 +205,74 @@ int close_pkt_sock(pkt_sock_t *const pkt_sock) return 0; } +static uint32_t _tx_pkt_to_iovec(odp_packet_t pkt, + struct iovec iovecs[ODP_BUFFER_MAX_SEG]) +{ + uint32_t pkt_len = odp_packet_len(pkt); + uint32_t offset = odp_packet_l2_offset(pkt); + uint32_t iov_count = 0; + + while (offset < pkt_len) { + uint32_t seglen; + + iovecs[iov_count].iov_base = odp_packet_offset(pkt, offset, + &seglen, NULL); + iovecs[iov_count].iov_len = seglen; + iov_count++; + offset += seglen; + } + + return iov_count; +} + +static uint32_t _rx_pkt_to_iovec(odp_packet_t pkt, + struct iovec iovecs[ODP_BUFFER_MAX_SEG]) +{ + odp_packet_seg_t seg = odp_packet_first_seg(pkt); + uint32_t seg_count = odp_packet_num_segs(pkt); + uint32_t seg_id = 0; + uint32_t iov_count = 0; + uint32_t headroom = odp_packet_headroom(pkt); + uint32_t tailroom = odp_packet_tailroom(pkt); + + for (seg_id = 0; seg_id < seg_count; ++seg_id) { + uint32_t seglen = odp_packet_seg_buf_len(pkt, seg); + uint8_t *ptr = odp_packet_seg_buf_addr(pkt, seg); + + if (headroom) { + uint32_t headlen = headroom > seglen ? + seglen : headroom; + + headroom -= headlen; + seglen -= headlen; + ptr += headlen; + } + if (odp_likely(seglen != 0)) { + iovecs[iov_count].iov_base = ptr; + iovecs[iov_count].iov_len = seglen; + iov_count++; + } + seg = odp_packet_next_seg(pkt, seg); + } + /* Now remove the tail room */ + while (tailroom > 0) { + uint32_t iov_len = iovecs[iov_count].iov_len; + + if (iov_len > tailroom) { + /* All the remaining tailroom is in this segment */ + iovecs[iov_count].iov_len -= tailroom; + tailroom = 0; + } else { + /* Tailroom is larger than the last segment. + * Remove this iovec and check the previous one */ + iov_count--; + tailroom -= iov_len; + } + } + + return iov_count; +} + /* * ODP_PACKET_SOCKET_MMSG: */ @@ -213,9 +282,7 @@ int recv_pkt_sock_mmsg(pkt_sock_t *const pkt_sock, const int sockfd = pkt_sock->sockfd; int msgvec_len; struct mmsghdr msgvec[ODP_PACKET_SOCKET_MAX_BURST_RX]; - struct iovec iovecs[ODP_PACKET_SOCKET_MAX_BURST_RX]; - uint8_t *pkt_buf; - uint8_t *l2_hdr; + struct iovec iovecs[ODP_PACKET_SOCKET_MAX_BURST_RX][ODP_BUFFER_MAX_SEG]; int nb_rx = 0; int recv_msgs; int i; @@ -231,12 +298,10 @@ int recv_pkt_sock_mmsg(pkt_sock_t *const pkt_sock, if (odp_unlikely(pkt_table[i] == ODP_PACKET_INVALID)) break; - pkt_buf = odp_packet_data(pkt_table[i]); - l2_hdr = pkt_buf + pkt_sock->frame_offset; - iovecs[i].iov_base = l2_hdr; - iovecs[i].iov_len = pkt_sock->max_frame_len; - msgvec[i].msg_hdr.msg_iov = &iovecs[i]; - msgvec[i].msg_hdr.msg_iovlen = 1; + msgvec[i].msg_hdr.msg_iovlen = + _rx_pkt_to_iovec(pkt_table[i], iovecs[i]); + + msgvec[i].msg_hdr.msg_iov = iovecs[i]; } msgvec_len = i; /* number of successfully allocated pkt buffers */ @@ -277,7 +342,7 @@ int send_pkt_sock_mmsg(pkt_sock_t *const pkt_sock, odp_packet_t pkt_table[], unsigned len) { struct mmsghdr msgvec[ODP_PACKET_SOCKET_MAX_BURST_TX]; - struct iovec iovecs[ODP_PACKET_SOCKET_MAX_BURST_TX]; + struct iovec iovecs[ODP_PACKET_SOCKET_MAX_BURST_TX][ODP_BUFFER_MAX_SEG]; int ret; int sockfd; unsigned i; @@ -291,11 +356,9 @@ int send_pkt_sock_mmsg(pkt_sock_t *const pkt_sock, memset(msgvec, 0, sizeof(msgvec)); for (i = 0; i < len; i++) { - uint32_t seglen; - iovecs[i].iov_base = odp_packet_l2_ptr(pkt_table[i], &seglen); - iovecs[i].iov_len = seglen; - msgvec[i].msg_hdr.msg_iov = &iovecs[i]; - msgvec[i].msg_hdr.msg_iovlen = 1; + msgvec[i].msg_hdr.msg_iov = iovecs[i]; + msgvec[i].msg_hdr.msg_iovlen = _tx_pkt_to_iovec(pkt_table[i], + iovecs[i]); } flags = MSG_DONTWAIT; _______________________________________________ lng-odp mailing list lng-odp@lists.linaro.org https://lists.linaro.org/mailman/listinfo/lng-odp