On 11/06/2014 03:56 PM, Bill Fischofer wrote:
In reworking the packet code, one point I'm not clear on is how the linux-generic raw socket I/O model is supposed to deal with segmented packets on both receive and transmit paths.

Transmit is presumably more straightforward. Here's a snippet from odp_packet_socket.c (routine

while (i < len) { pkt = pkt_table[i]; frame = odp_packet_l2(pkt); frame_len = odp_packet_get_len(pkt); ret = send(sockfd, frame, frame_len, flags); if (odp_unlikely(ret == -1)) { if (odp_likely(errno == EAGAIN)) { flags = 0; /* blocking for next rounds */ continue; /* resend buffer */ } else { break; } } i++; } /* end while */

The current code assumes that it has contiguous addressability to the entire packet. Is that a requirement of the raw socket interface? If not then it would seem this could be replaced by the following more general code:

while (i < len) {
pkt = pkt_table[i];

frame_len = odp_packet_len(pkt);
frame_offset = 0;

while (frame_len > 0) {
frame = odp_packet_offset_map(pkt,frame_offset,&seglen);
if (frame == NULL)
break;
ret = send(sockfd, frame, seg_len, flags);

I think raw sockets expect that packet is in continuous memory. You can relay on that on receive but on send you never know how that packet was created. For example app can create segmented packets, segments are in different address. In that case you need to copy that data to temporary buffer before sending.

 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
Works with vectors:

           struct msghdr {
               void         *msg_name;       /* optional address */
               socklen_t     msg_namelen;    /* size of address */
               struct iovec *msg_iov;        /* scatter/gather array */
               size_t        msg_iovlen;     /* # elements in msg_iov */
void *msg_control; /* ancillary data, see below */ size_t msg_controllen; /* ancillary data buffer len */ int msg_flags; /* flags on received message */
           };

But for raw sockets more likely that each entry in vector will be separate packet. But it's needed to check if it's so or not.

Maxim.

if (odp_unlikely(ret == -1)) {
if (odp_likely(errno == EAGAIN)) {
flags = 0;/* blocking for next rounds */
continue;/* resend buffer */
} else {
frame_offset += seg_len;
frame_len  -= seg_len;
}
}
}
i++;
}/* end while */

Would this code be functionally correct from a raw socket perspective?

Receive processing has similar issues. I've not been able to find any raw socket examples (via googling) that don't assume they can receive an entire packet into a single contiguous buffer. Is that a requirement of the interface?

Is there support for scatter/gather lists in these APIs? If so then we may need some additional ODP APIs (possibly internal) to allow the segment lists to be manipulated as a whole rather than one-by-one.

Thanks.

Bill


_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/lng-odp


_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to