/*
 * vr_nl_uvhost_connect - connect to the user space vhost server on a UNIX
 * domain socket.
 *
 * Returns 0 on success, error otherwise.
 */
static int
vr_nl_uvhost_connect(void)
{
    int s = 0, ret = -1, err;
    struct sockaddr_un nl_sun, uvh_sun;

    s = socket(AF_UNIX, SOCK_SEQPACKET, 0);
    if (s == -1) {
        RTE_LOG(ERR, VROUTER, "    error creating uvhost socket: %s (%d)\n",
                        rte_strerror(errno), errno);
        goto error;
    }
    RTE_LOG(INFO, VROUTER, "    uvhost Unix socket FD is %d\n", s);

    memset(&nl_sun, 0, sizeof(nl_sun));
    nl_sun.sun_family = AF_UNIX;
    strncpy(nl_sun.sun_path, vr_socket_dir, sizeof(nl_sun.sun_path) - 1);
    strncat(nl_sun.sun_path, "/"VR_NL_UVH_SOCK_NAME, sizeof(nl_sun.sun_path)
        - strlen(nl_sun.sun_path) - 1);

    mkdir(vr_socket_dir, VR_DEF_SOCKET_DIR_MODE);
    unlink(nl_sun.sun_path);
    ret = bind(s, (struct sockaddr *) &nl_sun, sizeof(nl_sun));
    if (ret == -1) {
        RTE_LOG(ERR, VROUTER, "    error binding uvhost FD %d to %s: %s (%d)\n",
                        s, nl_sun.sun_path, rte_strerror(errno), errno);
        goto error;
    }

    /*
     * This will block until the user space vhost thread listens on the
     * socket.
     */
    memset(&uvh_sun, 0, sizeof(uvh_sun));
    uvh_sun.sun_family = AF_UNIX;
    strncpy(uvh_sun.sun_path, vr_socket_dir, sizeof(uvh_sun.sun_path) - 1);
    strncat(uvh_sun.sun_path, "/"VR_UVH_NL_SOCK_NAME, sizeof(uvh_sun.sun_path)
        - strlen(uvh_sun.sun_path) - 1);

    ret = vr_dpdk_retry_connect(s, (struct sockaddr *) &uvh_sun, sizeof(uvh_sun));
    if (ret == -1) {
        RTE_LOG(ERR, VROUTER, "    error connecting uvhost socket FD %d to %s:"
            " %s (%d)\n", s, uvh_sun.sun_path, rte_strerror(errno), errno);
        goto error;
    }

    vr_nl_uvh_sock = s;

    return 0;

error:

    err = errno;
    if (s > 0) {
        close(s);
    }
    errno = err;

    return ret;
}
static int
vr_usocket_connect(struct vr_usocket *usockp)
{
    struct sockaddr_un sun;

    RTE_LOG(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(),
                usockp->usock_fd);
    if (usockp->usock_proto != PACKET)
        return -EINVAL;

    sun.sun_family = AF_UNIX;
    memset(sun.sun_path, 0, sizeof(sun.sun_path));
    strncpy(sun.sun_path, VR_PACKET_AGENT_UNIX_FILE, sizeof(sun.sun_path) - 1);

#ifdef VR_DPDK_USOCK_DUMP
    RTE_LOG(DEBUG, USOCK, "%s[%lx]: FD %d retry connecting\n", __func__,
            pthread_self(), usockp->usock_fd);
    rte_hexdump(stdout, "usock address dump:", &sun, sizeof(sun));
#endif
    return vr_dpdk_retry_connect(usockp->usock_fd, (struct sockaddr *)&sun,
                                        sizeof(sun));
}