Zero-Copy Receive Example #2

Onload User Guide (UG1586)

Document ID
UG1586
Release Date
2023-07-31
Revision
1.2 English
Figure 1. Zero-Copy Receive Example #2
static enum onload_zc_callback_rc
zc_recv_callback(struct onload_zc_recv_args *args, int flag)
{
  struct user_info *zc_info = args->user_ptr;
  int i, zc_rc = 0;
  for( i = 0; i < args->msg.msghdr.msg_iovlen; ++i ) {
    zc_rc += args->msg.iov[i].iov_len;
    handle_msg(args->msg.iov[i].iov_base,
               args->msg.iov[i].iov_len);
  }
  if( zc_rc == 0 )
    return ONLOAD_ZC_TERMINATE;
  zc_info->zc_rc += zc_rc;
  if( (zc_info->flags & MSG_WAITALL) &&
      (zc_info->zc_rc < zc_info->size) )
    return ONLOAD_ZC_CONTINUE;
  else return ONLOAD_ZC_TERMINATE;
}
struct onload_zc_recv_args zc_args;
ssize_t do_recv_zc(int fd, void* buf, size_t len, int flags)
{
  struct user_info info; int rc;
  init_user_info(&info);
  memset(&zc_args, 0, sizeof(zc_args));
  zc_args.user_ptr = &info;
  zc_args.flags = 0;
  zc_args.cb = &zc_recv_callback;
  if( flags & MSG_DONTWAIT )
    zc_args.flags |= ONLOAD_MSG_DONTWAIT;
  rc = onload_zc_recv(fd, &zc_args);
  if( rc == -ENOTEMPTY) {
    if( ( rc = onload_recvmsg_kernel(fd, &msg, 0) ) < 0 )
      printf("onload_recvmsg_kernel failed\n");
  }
  else if( rc == 0 ) {
    /* zc_rc gets set by callback to bytes received, so we
     * can return that to appear like standard recv call */
    rc = info.zc_rc;
  }
  return rc;
}
Note: onload_zc_recv() should not be used together with onload_set_recv_filter() and only supports accelerated (Onloaded) sockets. For example, when bound to a broadcast address the socket fd is handed off to the kernel and this function will return ESOCKNOTSUPPORT.