Пример #1
0
int
dpdk_packet_io(void)
{
    int ret;
    struct vr_dpdk_lcore *lcore = vr_dpdk.lcores[rte_lcore_id()];

wait_for_connection:
    RTE_LOG(DEBUG, VROUTER, "%s[%lx]: waiting for packet transport\n",
                __func__, pthread_self());
    while (!vr_dpdk.packet_transport) {
        /* handle an IPC command */
        if (unlikely(vr_dpdk_lcore_cmd_handle(lcore)))
            return -1;
        usleep(VR_DPDK_SLEEP_SERVICE_US);
    }

    RTE_LOG(DEBUG, VROUTER, "%s[%lx]: FD %d\n", __func__, pthread_self(),
                ((struct vr_usocket *)vr_dpdk.packet_transport)->usock_fd);
    ret = vr_usocket_io(vr_dpdk.packet_transport);
    if (ret < 0) {
        vr_dpdk.packet_transport = NULL;
        /* handle an IPC command */
        if (unlikely(vr_dpdk_lcore_cmd_handle(lcore)))
            return -1;
        usleep(VR_DPDK_SLEEP_SERVICE_US);
        goto wait_for_connection;
    }

    return ret;
}
/*
 * start io on socket
 */
int
vr_usocket_io(void *transport)
{
    int ret, i, processed;
    int timeout;
    struct pollfd *pfd;
    struct vr_usocket *usockp = (struct vr_usocket *)transport;
    unsigned lcore_id = rte_lcore_id();
    struct vr_dpdk_lcore *lcore = vr_dpdk.lcores[lcore_id];

    if (!usockp)
        return -1;

    RTE_LOG(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(),
                usockp->usock_fd);
    if ((ret = usock_init_poll(usockp)))
        goto return_from_io;

    pfd = &usockp->usock_pfds[0];
    pfd->fd = usockp->usock_fd;
    pfd->events = POLLIN;

    usockp->usock_io_in_progress = 1;

    timeout = usockp->usock_poll_block ? INFINITE_TIMEOUT : 0;
    while (1) {
        if (usockp->usock_should_close) {
            usock_close(usockp);
            return -1;
        }

        /*
         * Handle an IPC commands for IO_LCORE_ID up
         * and just check the stop flag for the rest.
         */
        if (lcore_id >= VR_DPDK_IO_LCORE_ID) {
            if (unlikely(vr_dpdk_lcore_cmd_handle(lcore)))
                break;
        } else {
            if (unlikely(vr_dpdk_is_stop_flag_set()))
                break;
        }

        rcu_thread_offline();
        ret = poll(usockp->usock_pfds, usockp->usock_max_cfds,
                timeout);
        if (ret < 0) {
            usock_set_error(usockp, ret);
            /* all other errors are fatal */
            if (errno != EINTR)
                goto return_from_io;
        }

        rcu_thread_online();

        processed = 0;
        pfd = usockp->usock_pfds;
        for (i = 0; (i < usockp->usock_max_cfds) && (processed < ret);
                i++, pfd++) {
            if ((pfd->fd >= 0)) {
                if (pfd->revents & POLLIN) {
                    if (i == 0) {
                        ret = vr_usocket_read(usockp);
                        if (ret < 0)
                            return ret;
                    } else {
                        vr_usocket_read(usockp->usock_children[i]);
                    }
                }

                if (pfd->revents & POLLOUT) {
                    usock_write(usockp->usock_children[i]);
                }

                if (pfd->revents & POLLHUP) {
                    if (i) {
                        usock_close(usockp->usock_children[i]);
                    } else {
                        break;
                    }
                }

                if (pfd->revents)
                    processed++;
            }
        }

        if (!timeout)
            return 0;
    }

return_from_io:
    usockp->usock_io_in_progress = 0;
    usock_deinit_poll(usockp);

    return ret;
}