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:
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)))
|
||||
{
|
||||
|
@ -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
@ -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 *
|
||||
|
Reference in New Issue
Block a user