PUNT socket: External control plane processes connected via UNIX domain sockets.
An external (to VPP) process can register (over the VPP binary API) to receive control plane packets over a UNIX domain socket. The packets are prepended with a packet descriptor containing meta-data (if_index of interface, etc). Currently only UDP is supported. The socket supports sending of packets/frames as well. The sent packet is prepended with a descriptor, telling VPP to route the packet (via ip4-lookup, ip6-lookup) or as an pre-formed Ethernet frame that is sent directly to interface-output. The intended use case for this is for an external DHCP client or a RIP implementation. New configuration option: punt { socket <socket path> } To register use the punt_socket API message. TODO: - Add support for pre-routing. I.e send L3 packet to given TX interface, but do ARP/ND (ip[46]-rewrite) - Add test scripts - Support for abstract names (starting with \0) - Add rate limiting (COP) - Support for other protocols, e.g. IPv6 ND Change-Id: I4a0afc8020deebb3d9d74686dde694ee5bcb8d0f Signed-off-by: Ole Troan <ot@cisco.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -20,6 +20,7 @@
|
||||
#ifndef included_punt_h
|
||||
#define included_punt_h
|
||||
|
||||
#include <sys/un.h>
|
||||
typedef enum
|
||||
{
|
||||
#define punt_error(n,s) PUNT_ERROR_##n,
|
||||
@ -30,9 +31,56 @@ typedef enum
|
||||
|
||||
|
||||
clib_error_t *vnet_punt_add_del (vlib_main_t * vm, u8 ipv,
|
||||
u8 protocol, u16 port, int is_add);
|
||||
u8 protocol, u16 port, bool is_add);
|
||||
clib_error_t *vnet_punt_socket_add (vlib_main_t * vm, u32 header_version,
|
||||
bool is_ip4, u8 protocol, u16 port,
|
||||
char *client_pathname);
|
||||
clib_error_t *vnet_punt_socket_del (vlib_main_t * vm, bool is_ip4,
|
||||
u8 l4_protocol, u16 port);
|
||||
char *vnet_punt_get_server_pathname (void);
|
||||
|
||||
#endif /* included_punt_h */
|
||||
enum punt_action_e
|
||||
{
|
||||
PUNT_L2 = 0,
|
||||
PUNT_IP4_ROUTED,
|
||||
PUNT_IP6_ROUTED,
|
||||
};
|
||||
|
||||
/*
|
||||
* Packet descriptor header. Version 1
|
||||
* If this header changes, the version must also change to notify clients.
|
||||
*/
|
||||
#define PUNT_PACKETDESC_VERSION 1
|
||||
typedef struct __attribute__ ((packed))
|
||||
{
|
||||
u32 sw_if_index; /* RX or TX interface */
|
||||
enum punt_action_e action;
|
||||
} punt_packetdesc_t;
|
||||
|
||||
/*
|
||||
* Client registration
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
u16 port;
|
||||
struct sockaddr_un caddr;
|
||||
} punt_client_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int socket_fd;
|
||||
char sun_path[sizeof (struct sockaddr_un)];
|
||||
punt_client_t *clients_by_dst_port4;
|
||||
punt_client_t *clients_by_dst_port6;
|
||||
u32 unix_file_index;
|
||||
bool is_configured;
|
||||
vlib_node_t *interface_output_node;
|
||||
u32 *ready_fds;
|
||||
u32 *rx_buffers;
|
||||
} punt_main_t;
|
||||
extern punt_main_t punt_main;
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
|
@ -17,3 +17,11 @@
|
||||
|
||||
punt_error (NONE, "no error")
|
||||
punt_error (UDP_PORT, "udp port punt")
|
||||
punt_error (SOCKET_RX, "Socket RX")
|
||||
punt_error (SOCKET_TX, "Socket TX")
|
||||
punt_error (SOCKET_RX_ERROR, "Socket RX error")
|
||||
punt_error (SOCKET_TX_ERROR, "Socket TX error")
|
||||
punt_error (NOBUFFER, "buffer allocation failure")
|
||||
punt_error (READV, "socket read failure")
|
||||
punt_error (ACTION, "invalid packet descriptor")
|
||||
|
||||
|
@ -144,6 +144,8 @@ _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, \
|
||||
ip_source_and_port_range_check_interface_add_del) \
|
||||
_(DELETE_SUBIF, delete_subif) \
|
||||
_(PUNT, punt) \
|
||||
_(PUNT_SOCKET_REGISTER, punt_socket_register) \
|
||||
_(PUNT_SOCKET_DEREGISTER, punt_socket_deregister) \
|
||||
_(FEATURE_ENABLE_DISABLE, feature_enable_disable)
|
||||
|
||||
#define QUOTE_(x) #x
|
||||
@ -1940,6 +1942,68 @@ vl_api_punt_t_handler (vl_api_punt_t * mp)
|
||||
REPLY_MACRO (VL_API_PUNT_REPLY);
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_punt_socket_register_t_handler (vl_api_punt_socket_register_t * mp)
|
||||
{
|
||||
vl_api_punt_socket_register_reply_t *rmp;
|
||||
vlib_main_t *vm = vlib_get_main ();
|
||||
int rv = 0;
|
||||
clib_error_t *error;
|
||||
unix_shared_memory_queue_t *q;
|
||||
u32 handle;
|
||||
|
||||
error = vnet_punt_socket_add (vm, ntohl (mp->header_version),
|
||||
mp->is_ip4, mp->l4_protocol,
|
||||
ntohs (mp->l4_port), (char *) mp->pathname);
|
||||
if (error)
|
||||
{
|
||||
rv = -1;
|
||||
clib_error_report (error);
|
||||
}
|
||||
|
||||
q = vl_api_client_index_to_input_queue (mp->client_index);
|
||||
if (!q)
|
||||
return;
|
||||
|
||||
rmp = vl_msg_api_alloc (sizeof (*rmp));
|
||||
rmp->_vl_msg_id = htons (VL_API_PUNT_SOCKET_REGISTER_REPLY);
|
||||
rmp->context = mp->context;
|
||||
rmp->retval = htonl (rv);
|
||||
char *p = vnet_punt_get_server_pathname ();
|
||||
/* Abstract pathnames start with \0 */
|
||||
memcpy ((char *) rmp->pathname, p, sizeof (rmp->pathname));
|
||||
vl_msg_api_send_shmem (q, (u8 *) & rmp);
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_punt_socket_deregister_t_handler (vl_api_punt_socket_deregister_t * mp)
|
||||
{
|
||||
vl_api_punt_socket_deregister_reply_t *rmp;
|
||||
vlib_main_t *vm = vlib_get_main ();
|
||||
int rv = 0;
|
||||
clib_error_t *error;
|
||||
unix_shared_memory_queue_t *q;
|
||||
u32 handle;
|
||||
|
||||
error = vnet_punt_socket_del (vm, mp->is_ip4, mp->l4_protocol,
|
||||
ntohs (mp->l4_port));
|
||||
if (error)
|
||||
{
|
||||
rv = -1;
|
||||
clib_error_report (error);
|
||||
}
|
||||
|
||||
q = vl_api_client_index_to_input_queue (mp->client_index);
|
||||
if (!q)
|
||||
return;
|
||||
|
||||
rmp = vl_msg_api_alloc (sizeof (*rmp));
|
||||
rmp->_vl_msg_id = htons (VL_API_PUNT_SOCKET_DEREGISTER_REPLY);
|
||||
rmp->context = mp->context;
|
||||
rmp->retval = htonl (rv);
|
||||
vl_msg_api_send_shmem (q, (u8 *) & rmp);
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_feature_enable_disable_t_handler (vl_api_feature_enable_disable_t * mp)
|
||||
{
|
||||
|
@ -991,6 +991,39 @@ autoreply define punt {
|
||||
u16 l4_port;
|
||||
};
|
||||
|
||||
/** \brief Punt traffic to the host via socket
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param header_version - expected meta data header version (currently 1)
|
||||
@param is_ip4 - L3 protocol 1 - IPv4, 0 - IPv6
|
||||
@param l4_protocol - L4 protocol to be punted, only UDP (0x11) is supported
|
||||
@param l4_port - TCP/UDP port to be punted
|
||||
*/
|
||||
define punt_socket_register {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u32 header_version;
|
||||
u8 is_ip4;
|
||||
u8 l4_protocol;
|
||||
u16 l4_port;
|
||||
u8 pathname[64];
|
||||
};
|
||||
|
||||
define punt_socket_register_reply
|
||||
{
|
||||
u32 context;
|
||||
i32 retval;
|
||||
u8 pathname[64];
|
||||
};
|
||||
|
||||
autoreply define punt_socket_deregister {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u8 is_ip4;
|
||||
u8 l4_protocol;
|
||||
u16 l4_port;
|
||||
};
|
||||
|
||||
/** \brief Feature path enable/disable request
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
|
Reference in New Issue
Block a user