Ejemplo n.º 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);
}
Ejemplo n.º 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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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);
  }

}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
/* SIG_DFL simulator for signals like SIGINT, SIGTERM: it is postponed
 * properly to safe shared stacks. */
static void citp_signal_terminate(int signum, siginfo_t *info, void *context)
{
  int fd;
  int rc;

  /* get any Onload fd to call ioctl */
  rc = ef_onload_driver_open(&fd, OO_STACK_DEV, 1);

  /* Die now:
   * _exit sets incorrect status in waitpid(), so we should try to exit via
   * signal.  Use _exit() if there is no other way. */
  if( rc == 0 )
    oo_resource_op(fd, OO_IOC_DIE_SIGNAL, &signum);
  else
    _exit(128 + signum);
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
static int fdtable_fd_move(ci_fd_t sock_fd, int op)
{
  ci_uint32 io_fd = sock_fd;
  int rc;

  oo_rwlock_lock_read(&citp_dup2_lock);
  rc = oo_resource_op(sock_fd, op, &io_fd);

  if( rc != 0 || io_fd == sock_fd ) {
    oo_rwlock_unlock_read(&citp_dup2_lock);
    return rc;
  }

  /* Kernel failed to hand over, but there is no epoll here - let's dup */
  rc = ci_sys_dup2(io_fd, sock_fd);
  ci_tcp_helper_close_no_trampoline(io_fd);
  oo_rwlock_unlock_read(&citp_dup2_lock);
  if( rc == sock_fd )
    return 0;
  else if( rc >= 0 )
    return -EINVAL;
  return rc;
}
Ejemplo n.º 9
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);
}
Ejemplo n.º 10
0
/* Returns:
 *          0                  on success
 *          
 *          CI_SOCKET_ERROR (and errno set)
 *                             this is a normal error that is returned to the
 *                             the application
 *
 *          CI_SOCKET_HANDOVER we tell the upper layers to handover, no need
 *                             to set errno since it isn't a real error
 */
int ci_tcp_connect(citp_socket* ep, const struct sockaddr* serv_addr,
		   socklen_t addrlen, ci_fd_t fd, int *p_moved)
{
  /* Address family is validated earlier. */
  struct sockaddr_in* inaddr = (struct sockaddr_in*) serv_addr;
  ci_sock_cmn* s = ep->s;
  ci_tcp_state* ts = &SOCK_TO_WAITABLE_OBJ(s)->tcp;
  int rc = 0, crc;
  ci_uint32 dst_be32;

  if( NI_OPTS(ep->netif).tcp_connect_handover )
    return CI_SOCKET_HANDOVER;

  /* Make sure we're up-to-date. */
  ci_netif_lock(ep->netif);
  CHECK_TEP(ep);
  ci_netif_poll(ep->netif);

  /*
   * 1. Check if state of the socket is OK for connect operation.
   */

 start_again:

  if( (rc = ci_tcp_connect_handle_so_error(s)) != 0) {
    CI_SET_ERROR(rc, rc);
    goto unlock_out;
  }

  if( s->b.state != CI_TCP_CLOSED ) {
    /* see if progress can be made on this socket before
    ** determining status  (e.g. non-blocking connect and connect poll)*/
    if( s->b.state & CI_TCP_STATE_SYNCHRONISED ) {
      if( ts->tcpflags & CI_TCPT_FLAG_NONBLOCK_CONNECT ) {
        ts->tcpflags &= ~CI_TCPT_FLAG_NONBLOCK_CONNECT;
	rc = 0;
	goto unlock_out;
      }
      if( serv_addr->sa_family == AF_UNSPEC )
        LOG_E(ci_log("Onload does not support TCP disconnect via "

                     "connect(addr->sa_family==AF_UNSPEC)"));
      CI_SET_ERROR(rc, EISCONN);
    }
    else if( s->b.state == CI_TCP_LISTEN ) {
#if CI_CFG_POSIX_CONNECT_AFTER_LISTEN
      CI_SET_ERROR(rc, EOPNOTSUPP);
#else
      if( ci_tcp_validate_sa(s->domain, serv_addr, addrlen) ) {
        /* Request should be forwarded to OS */
        rc = CI_SOCKET_HANDOVER;
	goto unlock_out;
      }
      if( serv_addr->sa_family == AF_UNSPEC ) {
        /* Linux does listen shutdown on disconnect (AF_UNSPEC) */
        ci_netif_unlock(ep->netif);
        rc = ci_tcp_shutdown(ep, SHUT_RD, fd);
	goto out;
      } else {
        /* Linux has curious error reporting in this case */
        CI_SET_ERROR(rc, EISCONN);
      }
#endif
    }
    else {
      /* Socket is in SYN-SENT state. Let's block for receiving SYN-ACK */
      ci_assert_equal(s->b.state, CI_TCP_SYN_SENT);
      if( s->b.sb_aflags & (CI_SB_AFLAG_O_NONBLOCK | CI_SB_AFLAG_O_NDELAY) )
        CI_SET_ERROR(rc, EALREADY);
      else
        goto syn_sent;
    }
    goto unlock_out;
  }

  /* Check if we've ever been connected. */
  if( ts->tcpflags & CI_TCPT_FLAG_WAS_ESTAB ) {
    CI_SET_ERROR(rc, EISCONN);
    goto unlock_out;
  }

  /* 
   * 2. Check address parameter, if it's inappropriate for handover
   *    decision or handover should be done, try to to call OS and
   *    do handover on success.
   */

  if (
    /* Af first, check that address family and length is OK. */
    ci_tcp_validate_sa(s->domain, serv_addr, addrlen)
    /* rfc793 p54 if the foreign socket is unspecified return          */
    /* "error: foreign socket unspecified" (EINVAL), but keep it to OS */
    || (dst_be32 = ci_get_ip4_addr(inaddr->sin_family, serv_addr)) == 0
    /* Zero destination port is tricky as well, keep it to OS */
    || inaddr->sin_port == 0 )
  {
    rc = CI_SOCKET_HANDOVER;
    goto unlock_out;
  }
  
  /* is this a socket that we can handle? */
  rc = ci_tcp_connect_check_dest(ep, dst_be32, inaddr->sin_port);
  if( rc )  goto unlock_out;

  if( (ts->s.pkt.flags & CI_IP_CACHE_IS_LOCALROUTE) &&
      OO_SP_IS_NULL(ts->local_peer) ) {
    /* Try to connect to another stack; handover if can't */
    struct oo_op_loopback_connect op;
    op.dst_port = inaddr->sin_port;
    op.dst_addr = dst_be32;
    /* this operation unlocks netif */
    rc = oo_resource_op(fd, OO_IOC_TCP_LOOPBACK_CONNECT, &op);
    if( rc < 0)
      return CI_SOCKET_HANDOVER;
    if( op.out_moved )
      *p_moved = 1;
    if( op.out_rc == -EINPROGRESS )
      RET_WITH_ERRNO( EINPROGRESS );
    else if( op.out_rc == -EAGAIN )
      return -EAGAIN;
    else if( op.out_rc != 0 )
      return CI_SOCKET_HANDOVER;
    return 0;
  }

  /* filters can't handle alien source address */
  if( (s->s_flags & CI_SOCK_FLAG_BOUND_ALIEN) &&
      ! (ts->s.pkt.flags & CI_IP_CACHE_IS_LOCALROUTE) ) {
    rc = CI_SOCKET_HANDOVER;
    goto unlock_out;
  }

  crc = ci_tcp_connect_ul_start(ep->netif, ts, dst_be32, inaddr->sin_port, &rc);
  if( crc != CI_CONNECT_UL_OK ) {
    switch( crc ) {
    case CI_CONNECT_UL_FAIL:
      goto unlock_out;
    case CI_CONNECT_UL_LOCK_DROPPED:
      goto out;
    case CI_CONNECT_UL_START_AGAIN:
      goto start_again;
    }
  }
  CI_TCP_STATS_INC_ACTIVE_OPENS( ep->netif );

 syn_sent:
  rc = ci_tcp_connect_ul_syn_sent(ep->netif, ts);

 unlock_out:
  ci_netif_unlock(ep->netif);
 out:
  return rc;
}