Figure 1. Zero-Copy with Single Message and Buffer Example
struct onload_zc_iovec iovec;
struct onload_zc_mmsg mmsg;
rc = onload_zc_alloc_buffers(fd, &iovec, 1,
ONLOAD_ZC_BUFFER_HDR_TCP);
assert(rc == O);
assert(my_data_len <= iovec.iov_len);
memcpy(iovec.iov_base, my_data, my_data_len);
iovec.iov_len = my_data_len;
mmsg.fd = fd;
mmsg.msg.iov = &iovec;
mmsg.msg.msghdr.msg_iovlen = 1;
rc = onload_zc_send(&mmsg, 1, 0);
if( rc <= 0) {
/* Probably application bug */
return rc;
} else {
/* Only one message, so rc should be 1 */
assert(rc == 1);
/* rc == 1 so we can look at the first (only) mmsg.rc */
if( mmsg.rc < 0 )
/* Error sending message */
onload_zc_release_buffers(fd, &iovec.buf, 1);
else
/* Message sent, single msg, single iovec so
* shouldn't worry about partial sends */
assert(mmsg.rc == my_data_len);
}
The example above demonstrates error code handling. Note it contains an examples of bad practice where buffers are allocated and populated on the critical path.