vppinfra: refactor clib_socket_init, add linux netns support

Type: improvement
Change-Id: Ida2d044bccf0bc8914b4fe7d383f827400fa6a52
Signed-off-by: Damjan Marion <dmarion@me.com>
This commit is contained in:
Damjan Marion
2023-01-30 11:48:38 +01:00
committed by Ole Tr�an
parent 0df06b6e95
commit 085757bb49
8 changed files with 501 additions and 354 deletions

View File

@ -73,7 +73,7 @@ memif_socket_filename_create_command_fn (vlib_main_t * vm,
return clib_error_return (0, "Invalid socket filename");
}
err = memif_socket_filename_add_del (1, socket_id, socket_filename);
err = memif_socket_filename_add_del (1, socket_id, (char *) socket_filename);
vec_free (socket_filename);

View File

@ -641,8 +641,8 @@ memif_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
{
clib_memset (sock, 0, sizeof(clib_socket_t));
sock->config = (char *) msf->filename;
sock->flags = CLIB_SOCKET_F_IS_CLIENT | CLIB_SOCKET_F_SEQPACKET |
CLIB_SOCKET_F_BLOCKING;
sock->is_seqpacket = 1;
sock->is_blocking = 1;
if ((err = clib_socket_init (sock)))
{
@ -675,79 +675,22 @@ memif_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
return 0;
}
/* *INDENT-OFF* */
VLIB_REGISTER_NODE (memif_process_node,static) = {
.function = memif_process,
.type = VLIB_NODE_TYPE_PROCESS,
.name = "memif-process",
};
/* *INDENT-ON* */
static clib_error_t *
memif_add_socket_file (u32 sock_id, u8 *socket_filename)
{
memif_main_t *mm = &memif_main;
uword *p;
memif_socket_file_t *msf;
p = hash_get (mm->socket_file_index_by_sock_id, sock_id);
if (p)
{
msf = pool_elt_at_index (mm->socket_files, *p);
if (strcmp ((char *) msf->filename, (char *) socket_filename) == 0)
{
/* Silently accept identical "add". */
return 0;
}
/* But don't allow a direct add of a different filename. */
return vnet_error (VNET_ERR_ENTRY_ALREADY_EXISTS,
"entry already exists");
}
pool_get (mm->socket_files, msf);
clib_memset (msf, 0, sizeof (memif_socket_file_t));
msf->filename = socket_filename;
msf->socket_id = sock_id;
hash_set (mm->socket_file_index_by_sock_id, sock_id,
msf - mm->socket_files);
return 0;
}
static clib_error_t *
memif_delete_socket_file (u32 sock_id)
{
memif_main_t *mm = &memif_main;
uword *p;
memif_socket_file_t *msf;
p = hash_get (mm->socket_file_index_by_sock_id, sock_id);
if (!p)
/* Don't delete non-existent entries. */
return vnet_error (VNET_ERR_INVALID_ARGUMENT,
"socket file with id %u does not exist", sock_id);
msf = pool_elt_at_index (mm->socket_files, *p);
if (msf->ref_cnt > 0)
return vnet_error (VNET_ERR_UNEXPECTED_INTF_STATE,
"socket file '%s' is in use", msf->filename);
vec_free (msf->filename);
pool_put (mm->socket_files, msf);
hash_unset (mm->socket_file_index_by_sock_id, sock_id);
return 0;
}
clib_error_t *
memif_socket_filename_add_del (u8 is_add, u32 sock_id, u8 *sock_filename)
memif_socket_filename_add_del (u8 is_add, u32 sock_id, char *sock_filename)
{
memif_main_t *mm = &memif_main;
uword *p;
memif_socket_file_t *msf;
clib_error_t *err = 0;
char *dir = 0, *tmp;
u32 idx = 0;
u8 *name = 0;
/* allow adding socket id 0 */
if (sock_id == 0 && is_add == 0)
@ -758,70 +701,95 @@ memif_socket_filename_add_del (u8 is_add, u32 sock_id, u8 *sock_filename)
"socked id is not specified");
if (is_add == 0)
return memif_delete_socket_file (sock_id);
{
p = hash_get (mm->socket_file_index_by_sock_id, sock_id);
if (!p)
/* Don't delete non-existent entries. */
return vnet_error (VNET_ERR_INVALID_ARGUMENT,
"socket file with id %u does not exist", sock_id);
msf = pool_elt_at_index (mm->socket_files, *p);
if (msf->ref_cnt > 0)
return vnet_error (VNET_ERR_UNEXPECTED_INTF_STATE,
"socket file '%s' is in use", msf->filename);
vec_free (msf->filename);
pool_put (mm->socket_files, msf);
hash_unset (mm->socket_file_index_by_sock_id, sock_id);
return 0;
}
if (sock_filename == 0 || sock_filename[0] == 0)
return vnet_error (VNET_ERR_INVALID_ARGUMENT,
"socket filename not specified");
if (sock_filename[0] != '/')
if (clib_socket_prefix_is_valid (sock_filename))
{
name = format (0, "%s%c", sock_filename, 0);
}
else if (sock_filename[0] == '/')
{
name = format (0, "%s%c", sock_filename, 0);
}
else
{
clib_error_t *error;
/* copy runtime dir path */
vec_add (dir, vlib_unix_get_runtime_dir (),
strlen (vlib_unix_get_runtime_dir ()));
vec_add1 (dir, '/');
/* if sock_filename contains dirs, add them to path */
tmp = strrchr ((char *) sock_filename, '/');
tmp = strrchr (sock_filename, '/');
if (tmp)
{
idx = tmp - (char *) sock_filename;
idx = tmp - sock_filename;
vec_add (dir, sock_filename, idx);
}
vec_add1 (dir, '\0');
/* create socket dir */
error = vlib_unix_recursive_mkdir (dir);
if (error)
if ((err = vlib_unix_recursive_mkdir (dir)))
{
clib_error_free (error);
return vnet_error (VNET_ERR_SYSCALL_ERROR_1,
"unable to create socket dir");
clib_error_free (err);
err = vnet_error (VNET_ERR_SYSCALL_ERROR_1,
"unable to create socket dir");
goto done;
}
sock_filename = format (0, "%s/%s%c", vlib_unix_get_runtime_dir (),
sock_filename, 0);
name =
format (0, "%s/%s%c", vlib_unix_get_runtime_dir (), sock_filename, 0);
}
else
p = hash_get (mm->socket_file_index_by_sock_id, sock_id);
if (p)
{
sock_filename = vec_dup (sock_filename);
/* check if directory exists */
tmp = strrchr ((char *) sock_filename, '/');
if (tmp)
msf = pool_elt_at_index (mm->socket_files, *p);
if (strcmp ((char *) msf->filename, (char *) name) == 0)
{
idx = tmp - (char *) sock_filename;
vec_add (dir, sock_filename, idx);
vec_add1 (dir, '\0');
/* Silently accept identical "add". */
goto done;
}
/* check dir existance and access rights for effective user/group IDs */
if ((dir == NULL)
||
(faccessat ( /* ignored */ -1, dir, F_OK | R_OK | W_OK, AT_EACCESS)
< 0))
{
vec_free (dir);
return vnet_error (
VNET_ERR_INVALID_ARGUMENT,
"directory doesn't exist or no access permissions");
}
/* But don't allow a direct add of a different filename. */
err = vnet_error (VNET_ERR_ENTRY_ALREADY_EXISTS, "entry already exists");
goto done;
}
vec_free (dir);
return memif_add_socket_file (sock_id, sock_filename);
pool_get (mm->socket_files, msf);
clib_memset (msf, 0, sizeof (memif_socket_file_t));
msf->filename = name;
msf->socket_id = sock_id;
name = 0;
hash_set (mm->socket_file_index_by_sock_id, sock_id, msf - mm->socket_files);
done:
vec_free (name);
vec_free (dir);
return err;
}
clib_error_t *
@ -949,24 +917,6 @@ memif_create_if (vlib_main_t *vm, memif_create_if_args_t *args)
/* Create new socket file */
if (msf->ref_cnt == 0)
{
struct stat file_stat;
/* If we are creating listener make sure file doesn't exist or if it
* exists thn delete it if it is old socket file */
if (args->is_master && (stat ((char *) msf->filename, &file_stat) == 0))
{
if (S_ISSOCK (file_stat.st_mode))
{
unlink ((char *) msf->filename);
}
else
{
err = vnet_error (VNET_ERR_VALUE_EXIST, "File exists for %s",
msf->filename);
goto done;
}
}
mhash_init (&msf->dev_instance_by_id, sizeof (uword),
sizeof (memif_interface_id_t));
msf->dev_instance_by_fd = hash_create (0, sizeof (uword));
@ -1068,9 +1018,11 @@ memif_create_if (vlib_main_t *vm, memif_create_if_args_t *args)
clib_memset (s, 0, sizeof (clib_socket_t));
s->config = (char *) msf->filename;
s->flags = CLIB_SOCKET_F_IS_SERVER |
CLIB_SOCKET_F_ALLOW_GROUP_WRITE |
CLIB_SOCKET_F_SEQPACKET | CLIB_SOCKET_F_PASSCRED;
s->local_only = 1;
s->is_server = 1;
s->allow_group_write = 1;
s->is_seqpacket = 1;
s->passcred = 1;
if ((err = clib_socket_init (s)))
{
@ -1159,9 +1111,7 @@ memif_init (vlib_main_t * vm)
* for socket-id 0 to MEMIF_DEFAULT_SOCKET_FILENAME in the
* default run-time directory.
*/
memif_socket_filename_add_del (1, 0, (u8 *) MEMIF_DEFAULT_SOCKET_FILENAME);
return 0;
return memif_socket_filename_add_del (1, 0, MEMIF_DEFAULT_SOCKET_FILENAME);
}
VLIB_INIT_FUNCTION (memif_init);

View File

@ -48,8 +48,6 @@ void
memif_main_t *mm = &memif_main;
u8 is_add;
u32 socket_id;
u32 len;
u8 *socket_filename;
vl_api_memif_socket_filename_add_del_reply_t *rmp;
int rv;
@ -65,19 +63,10 @@ void
}
/* socket filename */
socket_filename = 0;
mp->socket_filename[ARRAY_LEN (mp->socket_filename) - 1] = 0;
len = strlen ((char *) mp->socket_filename);
if (mp->is_add)
{
vec_validate (socket_filename, len);
memcpy (socket_filename, mp->socket_filename, len);
}
rv = vnet_api_error (
memif_socket_filename_add_del (is_add, socket_id, socket_filename));
vec_free (socket_filename);
rv = vnet_api_error (memif_socket_filename_add_del (
is_add, socket_id, (char *) mp->socket_filename));
reply:
REPLY_MACRO (VL_API_MEMIF_SOCKET_FILENAME_ADD_DEL_REPLY);

View File

@ -322,7 +322,7 @@ typedef struct
} memif_create_if_args_t;
clib_error_t *memif_socket_filename_add_del (u8 is_add, u32 sock_id,
u8 *sock_filename);
char *sock_filename);
clib_error_t *memif_create_if (vlib_main_t *vm, memif_create_if_args_t *args);
clib_error_t *memif_delete_if (vlib_main_t *vm, memif_if_t *mif);
clib_error_t *memif_plugin_api_hookup (vlib_main_t * vm);

View File

@ -259,8 +259,10 @@ snort_listener_init (vlib_main_t *vm)
s = clib_mem_alloc (sizeof (clib_socket_t));
clib_memset (s, 0, sizeof (clib_socket_t));
s->config = (char *) sm->socket_name;
s->flags = CLIB_SOCKET_F_IS_SERVER | CLIB_SOCKET_F_ALLOW_GROUP_WRITE |
CLIB_SOCKET_F_SEQPACKET | CLIB_SOCKET_F_PASSCRED;
s->is_server = 1;
s->allow_group_write = 1;
s->is_seqpacket = 1;
s->passcred = 1;
if ((err = clib_socket_init (s)))
{

View File

@ -53,6 +53,12 @@
#define CLIB_UNIX
#endif
#ifdef __linux__
#define CLIB_LINUX 1
#else
#define CLIB_LINUX 0
#endif
#include <vppinfra/types.h>
#include <vppinfra/atomics.h>

File diff suppressed because it is too large Load Diff

View File

@ -46,6 +46,16 @@
#include <vppinfra/error.h>
#include <vppinfra/format.h>
typedef enum
{
CLIB_SOCKET_TYPE_UNKNOWN = 0,
CLIB_SOCKET_TYPE_INET,
CLIB_SOCKET_TYPE_UNIX,
#if CLIB_LINUX
CLIB_SOCKET_TYPE_LINUX_ABSTRACT,
#endif
} clib_socket_type_t;
typedef struct _socket_t
{
/* File descriptor. */
@ -54,15 +64,21 @@ typedef struct _socket_t
/* Config string for socket HOST:PORT or just HOST. */
char *config;
u32 flags;
#define CLIB_SOCKET_F_IS_SERVER (1 << 0)
#define CLIB_SOCKET_F_IS_CLIENT (0 << 0)
#define CLIB_SOCKET_F_RX_END_OF_FILE (1 << 2)
#define CLIB_SOCKET_F_NON_BLOCKING_CONNECT (1 << 3)
#define CLIB_SOCKET_F_ALLOW_GROUP_WRITE (1 << 4)
#define CLIB_SOCKET_F_SEQPACKET (1 << 5)
#define CLIB_SOCKET_F_PASSCRED (1 << 6)
#define CLIB_SOCKET_F_BLOCKING (1 << 7)
union
{
struct
{
u32 is_server : 1;
u32 rx_end_of_file : 1;
u32 non_blocking_connect : 1;
u32 allow_group_write : 1;
u32 is_seqpacket : 1;
u32 passcred : 1;
u32 is_blocking : 1;
u32 local_only : 1;
};
u32 flags;
};
/* Transmit buffer. Holds data waiting to be written. */
u8 *tx_buffer;
@ -85,9 +101,18 @@ typedef struct _socket_t
int fds[], int num_fds);
clib_error_t *(*sendmsg_func) (struct _socket_t * s, void *msg, int msglen,
int fds[], int num_fds);
clib_socket_type_t type;
uword private_data;
} clib_socket_t;
#define CLIB_SOCKET_FLAG(f) (((clib_socket_t){ .f = 1 }).flags)
#define CLIB_SOCKET_F_IS_CLIENT 0
#define CLIB_SOCKET_F_IS_SERVER CLIB_SOCKET_FLAG (is_server)
#define CLIB_SOCKET_F_ALLOW_GROUP_WRITE CLIB_SOCKET_FLAG (allow_group_write)
#define CLIB_SOCKET_F_SEQPACKET CLIB_SOCKET_FLAG (is_seqpacket)
#define CLIB_SOCKET_F_PASSCRED CLIB_SOCKET_FLAG (passcred)
#define CLIB_SOCKET_F_BLOCKING CLIB_SOCKET_FLAG (is_blocking)
/* socket config format is host:port.
Unspecified port causes a free one to be chosen starting
from IPPORT_USERRESERVED (5000). */
@ -98,10 +123,12 @@ clib_error_t *clib_socket_init_netns (clib_socket_t *socket, u8 *namespace);
clib_error_t *clib_socket_accept (clib_socket_t * server,
clib_socket_t * client);
int clib_socket_prefix_is_valid (char *s);
always_inline uword
clib_socket_is_server (clib_socket_t * sock)
{
return (sock->flags & CLIB_SOCKET_F_IS_SERVER) != 0;
return sock->is_server;
}
always_inline uword
@ -120,7 +147,7 @@ clib_socket_is_connected (clib_socket_t * sock)
always_inline int
clib_socket_rx_end_of_file (clib_socket_t * s)
{
return s->flags & CLIB_SOCKET_F_RX_END_OF_FILE;
return s->rx_end_of_file;
}
always_inline void *