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