vnet_main_t *vnm = vnet_get_main ();
int num_rings = mif->num_s2m_rings + mif->num_m2s_rings;
memif_ring_data_t *rd = NULL;
+ vnet_hw_interface_t *hw;
+ u8 rid, rx_queues;
+ int ret;
vec_validate_aligned (mif->ring_data, num_rings - 1, CLIB_CACHE_LINE_BYTES);
vec_foreach (rd, mif->ring_data)
mif->flags |= MEMIF_IF_FLAG_CONNECTED;
vnet_hw_interface_set_flags (vnm, mif->hw_if_index,
VNET_HW_INTERFACE_FLAG_LINK_UP);
+
+ hw = vnet_get_hw_interface (vnm, mif->hw_if_index);
+ hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_INT_MODE;
+ vnet_hw_interface_set_input_node (vnm, mif->hw_if_index,
+ memif_input_node.index);
+ rx_queues = memif_get_rx_queues (mif);
+ for (rid = 0; rid < rx_queues; rid++)
+ {
+ vnet_hw_interface_assign_rx_thread (vnm, mif->hw_if_index, rid, ~0);
+ ret = vnet_hw_interface_set_rx_mode (vnm, mif->hw_if_index, rid,
+ VNET_HW_INTERFACE_RX_MODE_INTERRUPT);
+ if (ret)
+ DEBUG_LOG ("Warning: unable to set rx mode for interface %d "
+ "queue %d: rc=%d", mif->hw_if_index, rid, ret);
+ }
}
static void
-memif_disconnect (vlib_main_t * vm, memif_if_t * mif)
+memif_disconnect_do (vlib_main_t * vm, memif_if_t * mif)
{
vnet_main_t *vnm = vnet_get_main ();
+ u8 rid, rx_queues;
+ int rv;
+ memif_shm_t **shm;
mif->flags &= ~(MEMIF_IF_FLAG_CONNECTED | MEMIF_IF_FLAG_CONNECTING);
if (mif->hw_if_index != ~0)
vnet_hw_interface_set_flags (vnm, mif->hw_if_index, 0);
- if (mif->interrupt_line.index != ~0)
- {
- unix_file_del (&unix_main,
- unix_main.file_pool + mif->interrupt_line.index);
- mif->interrupt_line.index = ~0;
- mif->interrupt_line.fd = -1; /* closed in unix_file_del */
- }
if (mif->connection.index != ~0)
{
unix_file_del (&unix_main, unix_main.file_pool + mif->connection.index);
mif->connection.fd = -1; /* closed in unix_file_del */
}
- // TODO: properly munmap + close memif-owned shared memory segments
+ rx_queues = memif_get_rx_queues (mif);
+ for (rid = 0; rid < rx_queues; rid++)
+ {
+ rv = vnet_hw_interface_unassign_rx_thread (vnm, mif->hw_if_index, rid);
+ if (rv)
+ DEBUG_LOG ("Warning: unable to unassign interface %d, "
+ "queue %d: rc=%d", mif->hw_if_index, rid, rv);
+ }
+
+ shm = (memif_shm_t **) mif->regions;
+ rv = munmap ((void *) *shm, mif->shared_mem_size);
+ if (rv)
+ DEBUG_UNIX_LOG ("Error: failed munmap call");
+
vec_free (mif->regions);
}
+void
+memif_disconnect (vlib_main_t * vm, memif_if_t * mif)
+{
+ if (mif->interrupt_line.index != ~0)
+ {
+ unix_file_del (&unix_main,
+ unix_main.file_pool + mif->interrupt_line.index);
+ mif->interrupt_line.index = ~0;
+ mif->interrupt_line.fd = -1; /* closed in unix_file_del */
+ }
+
+ memif_disconnect_do (vm, mif);
+}
+
static clib_error_t *
memif_process_connect_req (memif_pending_conn_t * pending_conn,
memif_msg_t * req, struct ucred *slave_cr,
goto response;
}
+ mif->shared_mem_size = req->shared_mem_size;
mif->log2_ring_size = req->log2_ring_size;
mif->num_s2m_rings = req->num_s2m_rings;
mif->num_m2s_rings = req->num_m2s_rings;
uf->private_data = mif->if_index << 1;
mif->connection = pending_conn->connection;
pool_put (mm->pending_conns, pending_conn);
+ pending_conn = 0;
memif_connect (vm, mif);
resp.version = MEMIF_VERSION;
resp.type = MEMIF_MSG_TYPE_CONNECT_RESP;
resp.retval = retval;
- send (fd, &resp, sizeof (resp), 0);
+ if (send (fd, &resp, sizeof (resp), 0) < 0)
+ {
+ DEBUG_UNIX_LOG ("Failed to send connection response");
+ error = clib_error_return_unix (0, "send fd %d", fd);
+ if (pending_conn)
+ memif_remove_pending_conn (pending_conn);
+ else
+ memif_disconnect (vm, mif);
+ }
+ if (retval > 0)
+ {
+ if (shm_fd >= 0)
+ close (shm_fd);
+ if (int_fd >= 0)
+ close (int_fd);
+ }
return error;
}
else
mif = vec_elt_at_index (mm->interfaces, uf->private_data >> 1);
+ /* Stop workers to avoid end of the world */
+ vlib_worker_thread_barrier_sync (vlib_get_main ());
+
/* receive the incoming message */
size = recvmsg (uf->file_descriptor, &mh, 0);
if (size != sizeof (memif_msg_t))
{
- if (size != 0)
+ if (size == 0)
{
- DEBUG_UNIX_LOG ("Malformed message received on fd %d",
- uf->file_descriptor);
- error = clib_error_return_unix (0, "recvmsg fd %d",
- uf->file_descriptor);
+ if (pending_conn)
+ memif_remove_pending_conn (pending_conn);
+ else
+ memif_disconnect_do (vm, mif);
+ goto return_ok;
}
+
+ DEBUG_UNIX_LOG ("Malformed message received on fd %d",
+ uf->file_descriptor);
+ error = clib_error_return_unix (0, "recvmsg fd %d",
+ uf->file_descriptor);
goto disconnect;
}
{
case MEMIF_MSG_TYPE_CONNECT_REQ:
if (pending_conn == 0)
+ DEBUG_LOG ("Received unexpected connection request");
+ else
{
- DEBUG_LOG ("Received unexpected connection request");
- return 0;
- }
-
- /* Read anciliary data */
- cmsg = CMSG_FIRSTHDR (&mh);
- while (cmsg)
- {
- if (cmsg->cmsg_level == SOL_SOCKET
- && cmsg->cmsg_type == SCM_CREDENTIALS)
+ /* Read anciliary data */
+ cmsg = CMSG_FIRSTHDR (&mh);
+ while (cmsg)
{
- cr = (struct ucred *) CMSG_DATA (cmsg);
+ if (cmsg->cmsg_level == SOL_SOCKET
+ && cmsg->cmsg_type == SCM_CREDENTIALS)
+ {
+ cr = (struct ucred *) CMSG_DATA (cmsg);
+ }
+ else if (cmsg->cmsg_level == SOL_SOCKET
+ && cmsg->cmsg_type == SCM_RIGHTS)
+ {
+ memcpy (fd_array, CMSG_DATA (cmsg), sizeof (fd_array));
+ }
+ cmsg = CMSG_NXTHDR (&mh, cmsg);
}
- else if (cmsg->cmsg_level == SOL_SOCKET
- && cmsg->cmsg_type == SCM_RIGHTS)
- {
- clib_memcpy (fd_array, CMSG_DATA (cmsg), sizeof (fd_array));
- }
- cmsg = CMSG_NXTHDR (&mh, cmsg);
+ error = memif_process_connect_req (pending_conn, &msg, cr,
+ fd_array[0], fd_array[1]);
}
-
- return memif_process_connect_req (pending_conn, &msg, cr,
- fd_array[0], fd_array[1]);
+ break;
case MEMIF_MSG_TYPE_CONNECT_RESP:
if (mif == 0)
- {
- DEBUG_LOG ("Received unexpected connection response");
- return 0;
- }
- return memif_process_connect_resp (mif, &msg);
+ DEBUG_LOG ("Received unexpected connection response");
+ else
+ error = memif_process_connect_resp (mif, &msg);
+ break;
case MEMIF_MSG_TYPE_DISCONNECT:
goto disconnect;
goto disconnect;
}
- return 0;
+return_ok:
+ vlib_worker_thread_barrier_release (vlib_get_main ());
+ return error;
disconnect:
if (pending_conn)
memif_remove_pending_conn (pending_conn);
else
memif_disconnect (vm, mif);
+ vlib_worker_thread_barrier_release (vlib_get_main ());
return error;
}
memif_int_fd_read_ready (unix_file_t * uf)
{
memif_main_t *mm = &memif_main;
- vlib_main_t *vm = vlib_get_main ();
+ vnet_main_t *vnm = vnet_get_main ();
memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data);
u8 b;
ssize_t size;
mif->interrupt_line.index = ~0;
mif->interrupt_line.fd = -1;
}
- vlib_node_set_interrupt_pending (vm, memif_input_node.index);
+ else if (size < 0)
+ DEBUG_UNIX_LOG ("Failed to read from socket");
+ else
+ vnet_device_input_set_interrupt_pending (vnm, mif->hw_if_index, b);
+
return 0;
}
goto error;
}
+ mif->shared_mem_size = msg.shared_mem_size;
vec_add1 (mif->regions, shm);
((memif_shm_t *) mif->regions[0])->cookie = 0xdeadbeef;
{
u16 slot = i * (1 << mif->log2_ring_size) + j;
ring->desc[j].region = 0;
- ring->desc[j].offset = buffer_offset + (slot * mif->buffer_size);
+ ring->desc[j].offset =
+ buffer_offset + (u32) (slot * mif->buffer_size);
ring->desc[j].buffer_length = mif->buffer_size;
}
}
u16 slot =
(i + mif->num_s2m_rings) * (1 << mif->log2_ring_size) + j;
ring->desc[j].region = 0;
- ring->desc[j].offset = buffer_offset + (slot * mif->buffer_size);
+ ring->desc[j].offset =
+ buffer_offset + (u32) (slot * mif->buffer_size);
ring->desc[j].buffer_length = mif->buffer_size;
}
}
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
fd_array[0] = mfd;
- clib_memcpy (CMSG_DATA (cmsg), fd_array, sizeof (fd_array));
+ memcpy (CMSG_DATA (cmsg), fd_array, sizeof (fd_array));
mif->flags |= MEMIF_IF_FLAG_CONNECTING;
rv = sendmsg (mif->connection.fd, &mh, 0);
f64 start_time, last_run_duration = 0, now;
sockfd = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (sockfd < 0)
+ {
+ DEBUG_UNIX_LOG ("socket AF_UNIX");
+ return 0;
+ }
sun.sun_family = AF_UNIX;
template.read_function = memif_conn_fd_read_ready;
}
}
- if (mif->lockp != 0)
- {
- clib_mem_free ((void *) mif->lockp);
- mif->lockp = 0;
- }
+ clib_spinlock_free (&mif->lockp);
mhash_unset (&mm->if_index_by_key, &mif->key, &mif->if_index);
vec_free (mif->socket_filename);
memif_worker_thread_enable ()
{
/* if worker threads are enabled, switch to polling mode */
+ /* *INDENT-OFF* */
foreach_vlib_main ((
{
vlib_node_set_state (this_vlib_main,
memif_input_node.index,
VLIB_NODE_STATE_POLLING);
}));
-
+ /* *INDENT-ON* */
return 0;
}
int
memif_worker_thread_disable ()
{
+ /* *INDENT-OFF* */
foreach_vlib_main ((
{
vlib_node_set_state (this_vlib_main,
memif_input_node.index,
VLIB_NODE_STATE_INTERRUPT);
}));
-
+ /* *INDENT-ON* */
return 0;
}
mif->connection.fd = mif->interrupt_line.fd = -1;
if (tm->n_vlib_mains > 1)
- {
- mif->lockp = clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES,
- CLIB_CACHE_LINE_BYTES);
- memset ((void *) mif->lockp, 0, CLIB_CACHE_LINE_BYTES);
- }
+ clib_spinlock_init (&mif->lockp);
if (!args->hw_addr_set)
{
mif->log2_ring_size = args->log2_ring_size;
mif->buffer_size = args->buffer_size;
- /* TODO: make configurable */
- mif->num_s2m_rings = 1;
- mif->num_m2s_rings = 1;
+ mif->num_s2m_rings = args->rx_queues;
+ mif->num_m2s_rings = args->tx_queues;
mhash_set_mem (&mm->if_index_by_key, &args->key, &mif->if_index, 0);
memif_main_t *mm = &memif_main;
memif_if_t *mif;
uword *p;
+ u32 hw_if_index;
p = mhash_get (&mm->if_index_by_key, &key);
if (p == NULL)
{
- clib_warning ("Memory interface with key 0x%" PRIx64 " does not exist",
- key);
+ DEBUG_LOG ("Memory interface with key 0x%" PRIx64 " does not exist",
+ key);
return VNET_API_ERROR_SYSCALL_ERROR_1;
}
mif = pool_elt_at_index (mm->interfaces, p[0]);
mif->flags |= MEMIF_IF_FLAG_DELETING;
/* bring down the interface */
- vnet_hw_interface_set_flags (vnm, mif->hw_if_index, 0);
vnet_sw_interface_set_flags (vnm, mif->sw_if_index, 0);
- /* remove the interface */
- ethernet_delete_interface (vnm, mif->hw_if_index);
- mif->hw_if_index = ~0;
+ hw_if_index = mif->hw_if_index;
memif_close_if (mm, mif);
+ /* remove the interface */
+ ethernet_delete_interface (vnm, hw_if_index);
if (pool_elts (mm->interfaces) == 0)
{
vlib_process_signal_event (vm, memif_process_node.index,