#include #include #include "ff_socket_ops.h" #include "ff_sysproto.h" #include "ff_api.h" #include "ff_epoll.h" #undef FF_SYSCALL_DECL #define FF_SYSCALL_DECL(ret, fn, none) \ static ret ff_sys_##fn(struct ff_##fn##_args *args); #include static int ff_sys_kqueue(struct ff_kqueue_args *args); static int ff_sys_kevent(struct ff_kevent_args *args); #define FF_MAX_BOUND_NUM 8 struct ff_bound_info { int fd; struct sockaddr addr; }; static struct ff_bound_info ff_bound_fds[FF_MAX_BOUND_NUM]; static int sockaddr_cmp(struct sockaddr *a, struct sockaddr *b) { struct sockaddr_in *sina, *sinb; sina = (struct sockaddr_in *)a; sinb = (struct sockaddr_in *)b; if (sina->sin_family != sinb->sin_family) { return 1; } if (sina->sin_port != sinb->sin_port) { return 1; } if (sina->sin_addr.s_addr != sinb->sin_addr.s_addr) { return 1; } return 0; } static int sockaddr_is_bound(struct sockaddr *addr) { int i; for (i = 0; i < FF_MAX_BOUND_NUM; i++) { struct ff_bound_info *info = &ff_bound_fds[i]; if (info->fd == 0) { continue; } if (sockaddr_cmp(&info->addr, addr) == 0) { return info->fd; } } return 0; } static int sockaddr_bind(int fd, struct sockaddr *addr) { int i; for (i = 0; i < FF_MAX_BOUND_NUM; i++) { struct ff_bound_info *info = &ff_bound_fds[i]; if (info->fd != 0) { continue; } info->fd = fd; rte_memcpy(&info->addr, addr, sizeof(struct sockaddr)); return 0; } return -1; } static int sockaddr_unbind(int fd) { int i; for (i = 0; i < FF_MAX_BOUND_NUM; i++) { struct ff_bound_info *info = &ff_bound_fds[i]; if (info->fd != fd) { continue; } info->fd = 0; return 0; } return -1; } static int ff_sys_socket(struct ff_socket_args *args) { return ff_socket(args->domain, args->type, args->protocol); } static int ff_sys_bind(struct ff_bind_args *args) { int bound_fd; int ret; bound_fd = sockaddr_is_bound(args->addr); if (bound_fd != 0 && bound_fd != args->fd) { return ff_dup2(bound_fd, args->fd); } ret = ff_bind(args->fd, args->addr, args->addrlen); if (ret == 0) { sockaddr_bind(args->fd, args->addr); } return ret; } static int ff_sys_listen(struct ff_listen_args *args) { return ff_listen(args->fd, args->backlog); } static int ff_sys_shutdown(struct ff_shutdown_args *args) { return ff_shutdown(args->fd, args->how); } static int ff_sys_getsockname(struct ff_getsockname_args *args) { return ff_getsockname(args->fd, args->name, args->namelen); } static int ff_sys_getpeername(struct ff_getpeername_args *args) { return ff_getpeername(args->fd, args->name, args->namelen); } static int ff_sys_getsockopt(struct ff_getsockopt_args *args) { return ff_getsockopt(args->fd, args->level, args->name, args->optval, args->optlen); } static int ff_sys_setsockopt(struct ff_setsockopt_args *args) { return ff_setsockopt(args->fd, args->level, args->name, args->optval, args->optlen); } static int ff_sys_accept(struct ff_accept_args *args) { return ff_accept(args->fd, args->addr, args->addrlen); } static int ff_sys_accept4(struct ff_accept4_args *args) { errno = ENOSYS; return -1; } static int ff_sys_connect(struct ff_connect_args *args) { return ff_connect(args->fd, args->addr, args->addrlen); } static ssize_t ff_sys_recv(struct ff_recv_args *args) { return ff_recv(args->fd, args->buf, args->len, args->flags); } static ssize_t ff_sys_recvfrom(struct ff_recvfrom_args *args) { return ff_recvfrom(args->fd, args->buf, args->len, args->flags, args->from, args->fromlen); } static ssize_t ff_sys_recvmsg(struct ff_recvmsg_args *args) { return ff_recvmsg(args->fd, args->msg, args->flags); } static ssize_t ff_sys_read(struct ff_read_args *args) { return ff_read(args->fd, args->buf, args->len); } static ssize_t ff_sys_readv(struct ff_readv_args *args) { return ff_readv(args->fd, args->iov, args->iovcnt); } static ssize_t ff_sys_send(struct ff_send_args *args) { return ff_send(args->fd, args->buf, args->len, args->flags); } static ssize_t ff_sys_sendto(struct ff_sendto_args *args) { return ff_sendto(args->fd, args->buf, args->len, args->flags, args->to, args->tolen); } static ssize_t ff_sys_sendmsg(struct ff_sendmsg_args *args) { return ff_sendmsg(args->fd, args->msg, args->flags); } static ssize_t ff_sys_write(struct ff_write_args *args) { return ff_write(args->fd, args->buf, args->len); } static ssize_t ff_sys_writev(struct ff_writev_args *args) { return ff_writev(args->fd, args->iov, args->iovcnt); } static int ff_sys_close(struct ff_close_args *args) { sockaddr_unbind(args->fd); return ff_close(args->fd); } static int ff_sys_ioctl(struct ff_ioctl_args *args) { return ff_ioctl(args->fd, args->com, args->data); } static int ff_sys_fcntl(struct ff_fcntl_args *args) { return ff_fcntl(args->fd, args->cmd, args->data); } static int ff_sys_epoll_create(struct ff_epoll_create_args *args) { DEBUG_LOG("to run ff_epoll_create, size:%d\n", args->size); return ff_epoll_create(args->size); } static int ff_sys_epoll_ctl(struct ff_epoll_ctl_args *args) { DEBUG_LOG("to run ff_epoll_ctl, epfd:%d, op:%d, fd:%d\n", args->epfd, args->op, args->fd); return ff_epoll_ctl(args->epfd, args->op, args->fd, args->event); } static int ff_sys_epoll_wait(struct ff_epoll_wait_args *args) { DEBUG_LOG("to run ff_epoll_wait, epfd:%d, maxevents:%d, timeout:%d\n", args->epfd, args->maxevents, args->timeout); return ff_epoll_wait(args->epfd, args->events, args->maxevents, args->timeout); } static int ff_sys_kqueue(struct ff_kqueue_args *args) { return ff_kqueue(); } static int ff_sys_kevent(struct ff_kevent_args *args) { return ff_kevent(args->kq, args->changelist, args->nchanges, args->eventlist, args->nevents, args->timeout); } static pid_t ff_sys_fork(struct ff_fork_args *args) { errno = ENOSYS; return -1; } static int ff_so_handler(int ops, void *args) { DEBUG_LOG("ff_so_handler ops:%d, epoll create ops:%d\n", ops, FF_SO_EPOLL_CREATE); switch(ops) { case FF_SO_SOCKET: return ff_sys_socket((struct ff_socket_args *)args); case FF_SO_BIND: return ff_sys_bind((struct ff_bind_args *)args); case FF_SO_LISTEN: return ff_sys_listen((struct ff_listen_args *)args); case FF_SO_CONNECT: return ff_sys_connect((struct ff_connect_args *)args); case FF_SO_SHUTDOWN: return ff_sys_shutdown((struct ff_shutdown_args *)args); case FF_SO_GETSOCKNAME: return ff_sys_getsockname((struct ff_getsockname_args *)args); case FF_SO_GETPEERNAME: return ff_sys_getpeername((struct ff_getpeername_args *)args); case FF_SO_GETSOCKOPT: return ff_sys_getsockopt((struct ff_getsockopt_args *)args); case FF_SO_SETSOCKOPT: return ff_sys_setsockopt((struct ff_setsockopt_args *)args); case FF_SO_ACCEPT: return ff_sys_accept((struct ff_accept_args *)args); case FF_SO_ACCEPT4: return ff_sys_accept4((struct ff_accept4_args *)args); case FF_SO_RECV: return ff_sys_recv((struct ff_recv_args *)args); case FF_SO_RECVFROM: return ff_sys_recvfrom((struct ff_recvfrom_args *)args); case FF_SO_RECVMSG: return ff_sys_recvmsg((struct ff_recvmsg_args *)args); case FF_SO_READ: return ff_sys_read((struct ff_read_args *)args); case FF_SO_READV: return ff_sys_readv((struct ff_readv_args *)args); case FF_SO_SEND: return ff_sys_send((struct ff_send_args *)args); case FF_SO_SENDTO: return ff_sys_sendto((struct ff_sendto_args *)args); case FF_SO_SENDMSG: return ff_sys_sendmsg((struct ff_sendmsg_args *)args); case FF_SO_WRITE: return ff_sys_write((struct ff_write_args *)args); case FF_SO_WRITEV: return ff_sys_writev((struct ff_writev_args *)args); case FF_SO_CLOSE: return ff_sys_close((struct ff_close_args *)args); case FF_SO_IOCTL: return ff_sys_ioctl((struct ff_ioctl_args *)args); case FF_SO_FCNTL: return ff_sys_fcntl((struct ff_fcntl_args *)args); case FF_SO_EPOLL_CREATE: return ff_sys_epoll_create((struct ff_epoll_create_args *)args); case FF_SO_EPOLL_CTL: return ff_sys_epoll_ctl((struct ff_epoll_ctl_args *)args); case FF_SO_EPOLL_WAIT: return ff_sys_epoll_wait((struct ff_epoll_wait_args *)args); case FF_SO_KQUEUE: return ff_sys_kqueue((struct ff_kqueue_args *)args); case FF_SO_KEVENT: return ff_sys_kevent((struct ff_kevent_args *)args); case FF_SO_FORK: return ff_sys_fork((struct ff_fork_args *)args); default: break; } errno = EINVAL; return (-1); } static void ff_handle_kevent(struct ff_so_context *sc) { struct ff_kevent_args *ka = sc->args; errno = 0; sc->result = ff_sys_kevent(ka); sc->error = errno; if (ka->nchanges) { ka->nchanges = 0; } if (sc->result == 0 && ka->nevents != 0) { return; } sc->status = FF_SC_REP; sem_post(&sc->wait_sem); } static inline void ff_handle_socket_ops(struct ff_so_context *sc) { if (!rte_spinlock_trylock(&sc->lock)) { return; } if (sc->status != FF_SC_REQ) { rte_spinlock_unlock(&sc->lock); return; } DEBUG_LOG("ff_handle_socket_ops sc:%p, status:%d, ops:%d\n", sc, sc->status, sc->ops); if (sc->ops == FF_SO_KEVENT) { ff_handle_kevent(sc); rte_spinlock_unlock(&sc->lock); return; } errno = 0; sc->result = ff_so_handler(sc->ops, sc->args); sc->error = errno; sc->status = FF_SC_REP; if (sc->ops == FF_SO_EPOLL_WAIT) { sem_post(&sc->wait_sem); } rte_spinlock_unlock(&sc->lock); } void ff_handle_each_context() { uint16_t i, nb_handled; rte_spinlock_lock(&ff_so_zone->lock); assert(ff_so_zone->count >= ff_so_zone->free); nb_handled = ff_so_zone->count - ff_so_zone->free; if (nb_handled) { for (i = 0; i < ff_so_zone->count; i++) { struct ff_so_context *sc = &ff_so_zone->sc[i]; if (sc->inuse == 0) { continue; } ff_handle_socket_ops(sc); nb_handled--; if (!nb_handled) { break; } } } rte_spinlock_unlock(&ff_so_zone->lock); }