Example #1
0
void citp_waitable_wakeup(ci_netif* ni, citp_waitable* w)
{
  oo_waitable_wake_t op;
  op.sock_id = w->bufid;
  oo_resource_op(ci_netif_get_driver_handle(ni),
                 OO_IOC_WAITABLE_WAKE, &op);
}
Example #2
0
int oo_os_sock_recvmsg(ci_netif* ni, oo_sp sock_p,
                       struct msghdr* msg, int flags)
{
  oo_os_sock_recvmsg_t op;
  int rc;

  op.sock_id = OO_SP_TO_INT(sock_p);
  op.sizeof_ptr = sizeof(void*);
  op.flags = flags;
  CI_USER_PTR_SET(op.msg_iov, msg->msg_iov);
  op.msg_iovlen = msg->msg_iovlen;
  CI_USER_PTR_SET(op.msg_name, msg->msg_name);
  op.msg_namelen = msg->msg_namelen;
  CI_USER_PTR_SET(op.msg_control, msg->msg_control);
  op.msg_controllen = msg->msg_controllen;
  rc = oo_resource_op(ci_netif_get_driver_handle(ni),
                      OO_IOC_OS_SOCK_RECVMSG, &op);
  ci_assert(op.rc >= 0 || rc < 0);
  if( rc == 0 ) {
    msg->msg_flags = op.flags;
    msg->msg_namelen = op.msg_namelen;
    if( msg->msg_controllen )
      msg->msg_controllen = op.msg_controllen;
    return op.rc;
  }
  return rc;
}
Example #3
0
ci_fd_t ci_udp_ep_ctor(citp_socket* ep, ci_netif* netif, int domain, int type)
{
  ci_udp_state* us;
  ci_fd_t fd;

  VERB( log(LPFIN "ctor( )" ) );

  ci_assert(ep);
  ci_assert(netif);

  ci_netif_lock(netif);
  us = ci_udp_get_state_buf(netif);
  if (!us) {
    ci_netif_unlock(netif);
    LOG_E(ci_log("%s: [%d] out of socket buffers", __FUNCTION__,NI_ID(netif)));
    return -ENOMEM;
  }

  /* It's required to set protocol before ci_tcp_helper_sock_attach()
   * since it's used to determine if TCP or UDP file operations should be
   * attached to the file descriptor in kernel. */
   sock_protocol(&us->s) = IPPROTO_UDP;

  /* NB: this attach will close the os_sock_fd */
  fd = ci_tcp_helper_sock_attach(ci_netif_get_driver_handle(netif),  
                                 SC_SP(&us->s), domain, type);
  if( fd < 0 ) {
    if( fd == -EAFNOSUPPORT )
      LOG_U(ci_log("%s: ci_tcp_helper_sock_attach (domain=%d, type=%d) "
                   "failed %d", __FUNCTION__, domain, type, fd));
    else
      LOG_E(ci_log("%s: ci_tcp_helper_sock_attach (domain=%d, type=%d) "
                   "failed %d", __FUNCTION__, domain, type, fd));
    ci_netif_unlock(netif);
    return fd;
  }

  ci_assert(~us->s.b.sb_aflags & CI_SB_AFLAG_ORPHAN);

  us->s.rx_errno = 0;
  us->s.tx_errno = 0;
  us->s.so_error = 0;
  us->s.cp.sock_cp_flags |= OO_SCP_UDP_WILD;

  ep->s = &us->s;
  ep->netif = netif;
  CHECK_UEP(ep);
  ci_netif_unlock(netif);
  return fd;
}
Example #4
0
int oo_os_sock_get(ci_netif* ni, oo_sp sock_p, oo_os_file* os_sock_out)
{
  oo_os_sock_fd_get_t op;
  int rc;

  oo_rwlock_lock_read(&citp_dup2_lock);
  op.sock_id = OO_SP_TO_INT(sock_p);
  rc = oo_resource_op(ci_netif_get_driver_handle(ni),
                      OO_IOC_OS_SOCK_FD_GET, &op);
  if( rc == 0 )
    *os_sock_out = op.fd_out;
  else
    oo_rwlock_unlock_read (&citp_dup2_lock);
  return rc;
}
Example #5
0
static void do_ofe_command(ci_netif *ni)
{
  char command[200];
  char *str = command;
  int rc;
  oo_ofe_config_t op;
  int i;

  if( ni->ofe == NULL )
    return;

  for( i = 0; i < cfg_argc; i++ )
    str += snprintf(str, sizeof(command) - (str - command), "%s ", cfg_argv[i]);
  op.len = str - command;
  CI_USER_PTR_SET(op.str, command);
  rc = oo_resource_op(ci_netif_get_driver_handle(ni), OO_IOC_OFE_CONFIG, &op);

  oo_resource_op(ci_netif_get_driver_handle(ni), OO_IOC_OFE_CONFIG_DONE, NULL);

  if( rc == 0 ) {
    ci_log("[%s] %s: OK", ni->state->pretty_name, command);
    return;
  }

  ci_log("[%s] Onload Filter Engine fails to process command\n\t%s",
         ni->state->pretty_name, command);
  if( ofe_engine_get_last_error(ni->ofe) != NULL )
    ci_log("OFE ERROR: %s", ofe_engine_get_last_error(ni->ofe));
  else {
    char err[CI_LOG_MAX_LINE];
    oo_resource_op(ci_netif_get_driver_handle(ni), OO_IOC_OFE_GET_LAST_ERROR, err);
    err[CI_LOG_MAX_LINE-1] = '\0';
    ci_log("OFE ERROR: %s", err);
  }

}
Example #6
0
int oo_os_sock_accept(ci_netif* ni, oo_sp sock_p, struct sockaddr *addr,
                      socklen_t *addrlen, int flags)
{
  oo_os_sock_accept_t op;
  int rc;

  op.sock_id = OO_SP_TO_INT(sock_p);
  CI_USER_PTR_SET(op.addr, addr);
  CI_USER_PTR_SET(op.addrlen, addrlen);
  op.flags = flags;

  rc = oo_resource_op(ci_netif_get_driver_handle(ni),
                      OO_IOC_OS_SOCK_ACCEPT, &op);

  return rc == 0 ? op.rc : rc;
}
Example #7
0
int citp_pipe_splice_read(citp_fdinfo* fdi, int alien_fd, loff_t* alien_off,
                          size_t len, int flags,
                          citp_lib_context_t* lib_context)
{
  citp_pipe_fdi* epi = fdi_to_pipe_fdi(fdi);
  int rc;
  int read_len = 0;
  int non_block = (flags & SPLICE_F_NONBLOCK) || (epi->pipe->aflags &
       (CI_PFD_AFLAG_NONBLOCK << CI_PFD_AFLAG_READER_SHIFT));
  if( ! fdi_is_reader(fdi) ) {
    errno = EINVAL;
    return -1;
  }
  if( alien_off ) {
    /* TODO support this */
    errno = ENOTSUP;
    return -1;
  }
  if( len == 0 )
    return 0;
  do {
    struct oo_splice_read_context ctx = {
      .alien_fd = alien_fd,
      .len = len,
      .lib_context = lib_context
    };
    rc = ci_pipe_zc_read(epi->ni, epi->pipe, len,
                         non_block ? MSG_DONTWAIT : 0,
                         oo_splice_read_cb, &ctx);
    if( rc > 0 )
      read_len += rc;
  } while(0);

  if( rc < 0 && errno == EPIPE && ! (flags & MSG_NOSIGNAL) ) {
    ci_sys_ioctl(ci_netif_get_driver_handle(epi->ni),
                 OO_IOC_KILL_SELF_SIGPIPE, NULL);
    return rc;
  }
  if( rc > 0 )
    return read_len;
  return rc;
}
Example #8
0
ci_fd_t ci_tcp_ep_ctor(citp_socket* ep, ci_netif* netif, int domain, int type)
{
  ci_tcp_state* ts;
  ci_fd_t fd;

  ci_assert(ep);
  ci_assert(netif);

  ci_netif_lock(netif);
  ts = ci_tcp_get_state_buf(netif);
  if( ts == NULL ) {
    ci_netif_unlock(netif);
    LOG_E(ci_log("%s: [%d] out of socket buffers", __FUNCTION__,NI_ID(netif)));
    return -ENOMEM;
  }

  fd = ci_tcp_helper_sock_attach(ci_netif_get_driver_handle(netif), S_SP(ts),
                                 domain, type);
  if( fd < 0 ) {
    if( fd == -EAFNOSUPPORT )
      LOG_U(ci_log("%s: ci_tcp_helper_sock_attach" \
                   "(domain=%d, type=%d) failed %d",
                   __FUNCTION__, domain, type, fd));
    else
      LOG_E(ci_log("%s: ci_tcp_helper_sock_attach" \
                   "(domain=%d, type=%d) failed %d",
                   __FUNCTION__, domain, type, fd));
  }
  else {
    ci_assert(~ts->s.b.sb_aflags & CI_SB_AFLAG_ORPHAN);
    /* Apply default sockbuf sizes now we've updated them from the kernel
    ** defaults. */
    ts->s.so.sndbuf = NI_OPTS(netif).tcp_sndbuf_def;
    ts->s.so.rcvbuf = NI_OPTS(netif).tcp_rcvbuf_def;
    ep->netif = netif;
    ep->s = &ts->s;
    CHECK_TEP(ep);
  }

  ci_netif_unlock(netif);
  return fd;
}
Example #9
0
int oo_os_sock_sendmsg_raw(ci_netif* ni, oo_sp sock_p,
                           const struct msghdr* msg, int flags)
{
  unsigned long socketcall_args[8];
  oo_os_sock_sendmsg_raw_t op;
  int rc;

  op.sock_id = OO_SP_TO_INT(sock_p);
  op.sizeof_ptr = sizeof(void*);
  op.flags = flags;
  CI_USER_PTR_SET(op.msg, msg);
  CI_USER_PTR_SET(op.socketcall_args, socketcall_args);

  oo_rwlock_lock_read(&citp_dup2_lock);
  rc = oo_resource_op(ci_netif_get_driver_handle(ni),
                      OO_IOC_OS_SOCK_SENDMSG_RAW, &op);
  oo_rwlock_unlock_read (&citp_dup2_lock);

  return rc;
}
Example #10
0
static int oo_pipe_ctor(ci_netif* netif, struct oo_pipe** out_pipe,
                        int fds[2], int flags)
{
  struct oo_pipe* p;
  int rc;

  ci_assert(netif);

  ci_netif_lock(netif);
  p = oo_pipe_buf_get(netif);
  if( !p ) {
    rc = -1;
    errno = ENOMEM;
    goto out;
  }

  if( flags & O_NONBLOCK ) {
    p->aflags = (CI_PFD_AFLAG_NONBLOCK << CI_PFD_AFLAG_READER_SHIFT) |
        (CI_PFD_AFLAG_NONBLOCK << CI_PFD_AFLAG_WRITER_SHIFT);
  }

  /* attach */
  rc = ci_tcp_helper_pipe_attach(ci_netif_get_driver_handle(netif),
                                 W_SP(&p->b), flags, fds);
  if( rc < 0 ) {
    LOG_E(ci_log("%s: ci_tcp_helper_pipe_attach %d", __FUNCTION__, rc));
    errno = -rc;
    rc = -1;
    goto out;
  }

  *out_pipe = p;

out:
  ci_netif_unlock(netif);

  return rc;
}
Example #11
0
int oo_os_sock_sendmsg(ci_netif* ni, oo_sp sock_p,
                       const struct msghdr* msg, int flags)
{
  oo_os_sock_sendmsg_t op;

  op.sock_id = OO_SP_TO_INT(sock_p);
  op.sizeof_ptr = sizeof(void*);
  op.flags = flags;
  CI_USER_PTR_SET(op.msg_iov, msg->msg_iov);
  op.msg_iovlen = msg->msg_iovlen;
  CI_USER_PTR_SET(op.msg_name, msg->msg_name);
  op.msg_namelen = msg->msg_namelen;
#ifdef __i386__
  /* compat cmsg is not handled in this function */
  ci_assert_equal(msg->msg_controllen, 0);
  op.msg_controllen = 0;
  CI_USER_PTR_SET(op.msg_control, NULL);
#else
  CI_USER_PTR_SET(op.msg_control, msg->msg_control);
  op.msg_controllen = msg->msg_controllen;
#endif
  return oo_resource_op(ci_netif_get_driver_handle(ni),
                        OO_IOC_OS_SOCK_SENDMSG, &op);
}
Example #12
0
int citp_pipe_splice_write(citp_fdinfo* fdi, int alien_fd, loff_t* alien_off,
                           size_t olen, int flags,
                           citp_lib_context_t* lib_context)
{
  citp_pipe_fdi* epi = fdi_to_pipe_fdi(fdi);
  int len_in_bufs = OO_PIPE_SIZE_TO_BUFS(olen);
  struct iovec iov_on_stack[CITP_PIPE_SPLICE_WRITE_STACK_IOV_LEN];
  struct iovec* iov = iov_on_stack;
  int want_buf_count;
  int rc;
  int bytes_to_read;
  int len = olen;
  int no_more = 1; /* for now we only run single loop */
  int written_total = 0;
  int non_block = (flags & SPLICE_F_NONBLOCK) || (epi->pipe->aflags &
      (CI_PFD_AFLAG_NONBLOCK << CI_PFD_AFLAG_WRITER_SHIFT));
  if( fdi_is_reader(fdi) ) {
    errno = EINVAL;
    return -1;
  }
  if( alien_off ) {
    /* TODO support this */
    errno = ENOTSUP;
    return -1;
  }
  do {
    int count;
    int iov_num;
    int bytes_to_write;
    struct ci_pipe_pkt_list pkts = {};
    struct ci_pipe_pkt_list pkts2;
    want_buf_count = len_in_bufs;
    /* We might need to wait for buffers here on the first iteration */
    rc = ci_pipe_zc_alloc_buffers(epi->ni, epi->pipe, want_buf_count,
                                  MSG_NOSIGNAL | (non_block || written_total ?
                                  MSG_DONTWAIT : 0),
                                  &pkts);
    if( rc < 0 && written_total ) {
      /* whatever the error we need to report already written_bytes */
      rc = written_total;
      break;
    }
    else if( rc < 0 )
      break;
    else if( pkts.count == 0 && non_block ) {
      errno = EAGAIN;
      rc = -1;
      break;
    }
    else
      ci_assert_gt(pkts.count, 0);
    count = pkts.count;

    if( count > CITP_PIPE_SPLICE_WRITE_STACK_IOV_LEN ) {
      void* niov = realloc(iov == iov_on_stack ? NULL : iov,
                           sizeof(*iov) * len_in_bufs);
      if( niov == NULL )
        /* we can still move quite a few pkts */
        count = CITP_PIPE_SPLICE_WRITE_STACK_IOV_LEN;
      else
        niov = iov;
    }

    ci_assert_ge(count, 1);

    iov_num = count;
    pkts2 = pkts;
    bytes_to_read = ci_pipe_list_to_iovec(epi->ni, epi->pipe, iov, &iov_num,
                                          &pkts2, len);

    citp_exit_lib_if(lib_context, TRUE);
    /* Note: the following call might be non-blocking as well as blocking */
    rc = readv(alien_fd, iov, count);
    citp_reenter_lib(lib_context);

    if( rc > 0 ) {
      bytes_to_write = rc;
      written_total += bytes_to_write;
      len -= bytes_to_write;
      no_more |= bytes_to_write < bytes_to_read;
    }
    else {
      bytes_to_write = 0;
      no_more = 1;
    }

    {
      /* pipe zc_write will write non_empty buffers and release the empty
       * ones */
      int rc2 = ci_pipe_zc_write(epi->ni, epi->pipe, &pkts, bytes_to_write,
                  CI_PIPE_ZC_WRITE_FLAG_FORCE | MSG_DONTWAIT | MSG_NOSIGNAL);
      (void) rc2;
      ci_assert_equal(rc2, bytes_to_write);
    }
    /* for now we will not be doing second iteration, to allow for that
     * we'd need to have guarantee that read will not block
     * e.g. insight into type of fd and a nonblokcing operation
     * (to name a valid case: socket, recvmsg) */
  } while( ! no_more );

  if( iov != iov_on_stack )
    free(iov);
  if( rc > 0 )
    return written_total;
  if( rc < 0 && errno == EPIPE && ! (flags & MSG_NOSIGNAL) ) {
    ci_sys_ioctl(ci_netif_get_driver_handle(epi->ni),
                 OO_IOC_KILL_SELF_SIGPIPE, NULL);
  }
  return rc;
}