21 #include <sys/types.h> 23 #include <sys/ioctl.h> 24 #include <sys/socket.h> 28 #include <sys/prctl.h> 35 #include <vpp/app/version.h> 41 #define DEBUG_LOG(...) clib_warning(__VA_ARGS__) 42 #define DEBUG_UNIX_LOG(...) clib_unix_warning(__VA_ARGS__) 44 #define DEBUG_LOG(...) 118 int shm_fd,
int int_fd)
135 (
"Connection request is missing shared memory file descriptor");
143 (
"Connection request is missing interrupt line file descriptor");
148 if (slave_cr ==
NULL)
150 DEBUG_LOG (
"Connection request is missing slave credentials");
159 (
"Connection request with unmatched key (0x%" PRIx64
")", req->
key);
168 (
"Connection request with non-matching listener (%d vs. %d)",
176 DEBUG_LOG (
"Memif slave does not accept connection requests");
184 (
"Memif with key 0x%" PRIx64
" is already connected", mif->
key);
199 (
"Unexpectedly small shared memory segment received from slave.");
206 shm_fd, 0)) == MAP_FAILED)
209 (
"Failed to map shared memory segment received from slave memif");
218 (
"Possibly corrupted shared memory segment received from slave memif");
235 template.file_descriptor = int_fd;
236 template.private_data = mif->
if_index;
252 if (send (fd, &resp,
sizeof (resp), 0) < 0)
278 DEBUG_LOG (
"Memif master does not accept connection responses");
284 DEBUG_LOG (
"Unexpected connection response");
303 int fd_array[2] = { -1, -1 };
304 char ctl[CMSG_SPACE (
sizeof (fd_array)) +
305 CMSG_SPACE (
sizeof (
struct ucred))] = { 0 };
306 struct msghdr mh = { 0 };
308 struct ucred *cr = 0;
310 struct cmsghdr *cmsg;
314 iov[0].iov_base = (
void *) &msg;
318 mh.msg_control = ctl;
319 mh.msg_controllen =
sizeof (ctl);
353 if (pending_conn == 0)
355 DEBUG_LOG (
"Received unexpected connection request");
360 cmsg = CMSG_FIRSTHDR (&mh);
363 if (cmsg->cmsg_level == SOL_SOCKET
364 && cmsg->cmsg_type == SCM_CREDENTIALS)
366 cr = (
struct ucred *) CMSG_DATA (cmsg);
368 else if (cmsg->cmsg_level == SOL_SOCKET
369 && cmsg->cmsg_type == SCM_RIGHTS)
371 memcpy (fd_array, CMSG_DATA (cmsg),
sizeof (fd_array));
373 cmsg = CMSG_NXTHDR (&mh, cmsg);
377 fd_array[0], fd_array[1]);
382 DEBUG_LOG (
"Received unexpected connection response");
391 DEBUG_LOG (
"Received unknown message type");
434 struct sockaddr_un client;
440 addr_len =
sizeof (client);
442 (
struct sockaddr *) &client, (socklen_t *) & addr_len);
453 template.file_descriptor = conn_fd;
454 template.private_data = (pending_conn->
index << 1) | 1;
464 struct msghdr mh = { 0 };
466 struct cmsghdr *cmsg;
469 int fd_array[2] = { -1, -1 };
470 char ctl[CMSG_SPACE (
sizeof (fd_array))];
496 DEBUG_LOG (
"Failed to create anonymous file");
502 DEBUG_UNIX_LOG (
"Failed to seal an anonymous file off from truncating");
508 DEBUG_UNIX_LOG (
"Failed to extend the size of an anonymous file");
513 MAP_SHARED, mfd, 0)) == MAP_FAILED)
550 iov[0].iov_base = (
void *) &msg;
556 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fd_array) < 0)
565 template.private_data = mif->
if_index;
568 memset (&ctl, 0,
sizeof (ctl));
569 mh.msg_control = ctl;
570 mh.msg_controllen =
sizeof (ctl);
571 cmsg = CMSG_FIRSTHDR (&mh);
572 cmsg->cmsg_len = CMSG_LEN (
sizeof (fd_array));
573 cmsg->cmsg_level = SOL_SOCKET;
574 cmsg->cmsg_type = SCM_RIGHTS;
576 memcpy (CMSG_DATA (cmsg), fd_array,
sizeof (fd_array));
598 if (fd_array[1] > -1)
608 struct sockaddr_un sun;
610 uword *event_data = 0, event_type;
613 f64 start_time, last_run_duration = 0, now;
615 sockfd = socket (AF_UNIX, SOCK_STREAM, 0);
621 sun.sun_family = AF_UNIX;
628 (
f64) 3 - last_run_duration);
654 now = vlib_time_now (vm);
655 if (now > start_time + 10e-6)
657 vlib_process_suspend (vm, 100e-6);
658 start_time = vlib_time_now (vm);
672 strncpy (sun.sun_path, (char *) mif->socket_filename,
673 sizeof (sun.sun_path) - 1);
676 (sockfd, (struct sockaddr *) &sun,
677 sizeof (struct sockaddr_un)) == 0)
679 mif->connection.fd = sockfd;
680 template.file_descriptor = sockfd;
681 template.private_data = mif->if_index << 1;
682 mif->connection.index = unix_file_add (&unix_main, &template);
683 memif_connect_master (vm, mif);
686 sockfd = socket (AF_UNIX, SOCK_STREAM, 0);
689 DEBUG_UNIX_LOG (
"socket AF_UNIX");
705 .name =
"memif-process",
728 if (pending_conn->listener_index == mif->listener_index)
730 memif_remove_pending_conn (pending_conn);
748 mhash_unset (&mm->if_index_by_key, &mif->key, &mif->if_index);
752 memset (mif, 0,
sizeof (*mif));
765 VLIB_NODE_STATE_POLLING);
779 VLIB_NODE_STATE_INTERRUPT);
799 return VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
802 memset (mif, 0,
sizeof (*mif));
821 rnd = (
u32) (now * 1e6);
824 memcpy (args->
hw_addr + 2, &rnd, sizeof (rnd));
837 ret = VNET_API_ERROR_SYSCALL_ERROR_1;
862 struct sockaddr_un un = { 0 };
863 struct stat file_stat;
869 if (!S_ISSOCK (file_stat.st_mode))
872 ret = VNET_API_ERROR_SYSCALL_ERROR_2;
878 if (listener->sock_dev == file_stat.st_dev &&
879 listener->sock_ino == file_stat.st_ino)
882 mif->listener_index = listener->index;
883 ++listener->usage_counter;
892 memset (listener, 0,
sizeof (*listener));
893 listener->socket.fd = -1;
894 listener->socket.index = ~0;
895 listener->index = listener - mm->
listeners;
898 if ((listener->socket.fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
900 ret = VNET_API_ERROR_SYSCALL_ERROR_3;
904 un.sun_family = AF_UNIX;
906 sizeof (un.sun_path) - 1);
908 if (setsockopt (listener->socket.fd, SOL_SOCKET, SO_PASSCRED,
909 &on, sizeof (on)) < 0)
911 ret = VNET_API_ERROR_SYSCALL_ERROR_4;
914 if (bind (listener->socket.fd, (
struct sockaddr *) &un,
917 ret = VNET_API_ERROR_SYSCALL_ERROR_5;
920 if (listen (listener->socket.fd, 1) == -1)
922 ret = VNET_API_ERROR_SYSCALL_ERROR_6;
928 ret = VNET_API_ERROR_SYSCALL_ERROR_7;
932 listener->sock_dev = file_stat.st_dev;
933 listener->sock_ino = file_stat.st_ino;
937 template.file_descriptor = listener->socket.fd;
938 template.private_data = listener->index;
950 if (!args->hw_addr_set &&
951 tm->n_vlib_mains > 1 &&
pool_elts (mm->interfaces) == 1)
964 if (mif->hw_if_index != ~0)
967 mif->hw_if_index = ~0;
984 clib_warning (
"Memory interface with key 0x%" PRIx64
" does not exist",
986 return VNET_API_ERROR_SYSCALL_ERROR_1;
1034 if (tr && tr->
count > 0)
1059 .version = VPP_BUILD_VER,
1060 .description =
"Packet Memory Interface (experimetal)",
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
void memif_disconnect(vlib_main_t *vm, memif_if_t *mif)
static int memfd_create(const char *name, unsigned int flags)
static clib_error_t * memif_conn_fd_accept_ready(unix_file_t *uf)
sll srl srl sll sra u16x4 i
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
unix_file_function_t * read_function
static uword * vlib_process_wait_for_event(vlib_main_t *vm)
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
vnet_main_t * vnet_get_main(void)
static void vlib_node_set_interrupt_pending(vlib_main_t *vm, u32 node_index)
uword mhash_unset(mhash_t *h, void *key, uword *old_value)
vlib_node_registration_t memif_input_node
(constructor) VLIB_REGISTER_NODE (memif_input_node)
static f64 vlib_time_now(vlib_main_t *vm)
#define MFD_ALLOW_SEALING
#define MEMIF_MSG_TYPE_DISCONNECT
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
static clib_error_t * memif_init(vlib_main_t *vm)
#define VNET_HW_INTERFACE_FLAG_LINK_UP
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
static void memif_close_if(memif_main_t *mm, memif_if_t *mif)
#define DEBUG_UNIX_LOG(...)
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
#define MEMIF_IF_FLAG_IS_SLAVE
#define MEMIF_MSG_TYPE_CONNECT_RESP
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
int memif_delete_if(vlib_main_t *vm, u64 key)
static vnet_sw_interface_t * vnet_get_hw_sw_interface(vnet_main_t *vnm, u32 hw_if_index)
memif_pending_conn_t * pending_conns
static clib_error_t * memif_int_fd_read_ready(unix_file_t *uf)
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
#define VLIB_INIT_FUNCTION(x)
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
memif_file_t interrupt_line
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
u32 per_interface_next_index
static u32 memif_eth_flag_change(vnet_main_t *vnm, vnet_hw_interface_t *hi, u32 flags)
static void memif_connect_master(vlib_main_t *vm, memif_if_t *mif)
u32 input_cpu_first_index
u8 * default_socket_filename
static uword unix_file_add(unix_main_t *um, unix_file_t *template)
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
uword mhash_set_mem(mhash_t *h, void *key, uword *new_value, uword *old_value)
#define clib_error_return_unix(e, args...)
clib_error_t * memif_plugin_api_hookup(vlib_main_t *vm)
#define pool_put(P, E)
Free an object E in pool P.
#define vec_dup(V)
Return copy of vector (no header, no alignment)
#define MEMIF_IF_FLAG_CONNECTING
int memif_create_if(vlib_main_t *vm, memif_create_if_args_t *args)
#define foreach_vlib_main(body)
#define MEMIF_MSG_TYPE_CONNECT_REQ
static clib_error_t * memif_conn_fd_read_ready(unix_file_t *uf)
static clib_error_t * memif_process_connect_req(memif_pending_conn_t *pending_conn, memif_msg_t *req, struct ucred *slave_cr, int shm_fd, int int_fd)
void mhash_init(mhash_t *h, uword n_value_bytes, uword n_key_bytes)
#define MEMIF_IF_FLAG_ADMIN_UP
int memif_worker_thread_disable()
#define vec_free(V)
Free vector's memory (no header).
static void memif_remove_pending_conn(memif_pending_conn_t *pending_conn)
#define clib_warning(format, args...)
#define MEMIF_IF_FLAG_CONNECTED
static uword * mhash_get(mhash_t *h, const void *key)
memif_ring_data_t * ring_data
static void clib_mem_free(void *p)
clib_error_t * ethernet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, u8 *address, u32 *hw_if_index_return, ethernet_flag_change_function_t flag_change)
#define clib_error_report(e)
#define MEMIF_DEFAULT_SOCKET_FILENAME
static void vlib_node_set_state(vlib_main_t *vm, u32 node_index, vlib_node_state_t new_state)
Set node dispatch state.
uword * thread_registrations_by_name
memif_listener_t * listeners
static void memif_connect(vlib_main_t *vm, memif_if_t *mif)
static vlib_main_t * vlib_get_main(void)
vnet_device_class_t memif_device_class
#define MEMIF_IF_FLAG_DELETING
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
int memif_worker_thread_enable()
static_always_inline memif_ring_t * memif_get_ring(memif_if_t *mif, memif_ring_type_t type, u16 ring_num)
#define hash_get_mem(h, key)
static void * clib_mem_alloc_aligned(uword size, uword align)
static u32 random_u32(u32 *seed)
32-bit random number generator
#define VLIB_REGISTER_NODE(x,...)
static vlib_thread_main_t * vlib_get_thread_main()
static vlib_node_registration_t memif_process_node
(constructor) VLIB_REGISTER_NODE (memif_process_node)
static clib_error_t * memif_process_connect_resp(memif_if_t *mif, memif_msg_t *resp)
#define vec_foreach(var, vec)
Vector iterator.
clib_error_t * vnet_sw_interface_set_flags(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
#define CLIB_CACHE_LINE_BYTES
static uword memif_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
static void unix_file_del(unix_main_t *um, unix_file_t *f)
static uword pool_elts(void *v)
Number of active elements in a pool.