37 #include <sys/socket.h> 41 #define foreach_punt_next \ 42 _ (PUNT4, "ip4-punt") \ 47 #define _(s,n) PUNT_NEXT_##s, 61 #define punt_next_punt(is_ip4) (is_ip4 ? PUNT_NEXT_PUNT4 : PUNT_NEXT_PUNT6) 71 #ifndef CLIB_MARCH_VARIANT 97 u32 n_left_from, *from, *to_next;
109 while (n_left_from > 0)
116 while (n_left_from > 0 && n_left_to_next > 0)
140 #define punt_error(n,s) s, 203 .name =
"ip4-udp-punt",
205 .vector_size =
sizeof (
u32),
212 #define _(s,n) [PUNT_NEXT_##s] = n, 219 .name =
"ip6-udp-punt",
221 .vector_size =
sizeof (
u32),
228 #define _(s,n) [PUNT_NEXT_##s] = n, 250 static struct sockaddr_un *
260 #ifndef CLIB_MARCH_VARIANT 263 char *client_pathname)
275 memcpy (c.
caddr.sun_path, client_pathname, sizeof (c.
caddr.sun_path));
276 c.
caddr.sun_family = AF_UNIX;
321 struct iovec *iovecs = 0;
328 for (i = 0; i < n_packets; i++)
360 struct sockaddr_un *caddr;
365 PUNT_ERROR_SOCKET_TX_ERROR, 1);
380 _vec_len (iovecs) = 0;
386 iov->iov_base = &packetdesc;
387 iov->iov_len =
sizeof (packetdesc);
418 while (b->
flags & VLIB_BUFFER_NEXT_PRESENT);
421 struct msghdr msg = {
423 .msg_namelen =
sizeof (*caddr),
425 .msg_iovlen =
vec_len (iovecs),
428 if (sendmsg (pm->
socket_fd, &msg, 0) < (ssize_t) l)
430 PUNT_ERROR_SOCKET_TX_ERROR, 1);
460 .name =
"ip4-udp-punt-socket",
464 .vector_size =
sizeof (
u32),
470 .name =
"ip6-udp-punt-socket",
473 .vector_size =
sizeof (
u32),
503 u32 n_left_to_next, next_index;
505 u32 error = PUNT_ERROR_NONE;
518 error = PUNT_ERROR_NOBUFFER;
523 io[0].iov_base = &packetdesc;
524 io[0].iov_len =
sizeof (packetdesc);
525 io[1].iov_base = b->
data;
526 io[1].iov_len = buffer_size;
528 size = readv (fd, io, 2);
530 if (size <= (
int) (
sizeof (packetdesc) +
sizeof (
ip4_header_t)))
533 error = PUNT_ERROR_READV;
537 b->
flags = VNET_BUFFER_F_LOCALLY_ORIGINATED;
542 switch (packetdesc.
action)
562 error = PUNT_ERROR_ACTION;
611 .name =
"punt-socket-rx",
613 .state = VLIB_NODE_STATE_INTERRUPT,
640 #ifndef CLIB_MARCH_VARIANT 644 char *client_pathname)
655 if (protocol != IP_PROTOCOL_UDP)
657 "only UDP protocol (%d) is supported, got %d",
658 IP_PROTOCOL_UDP, protocol);
660 if (port == (
u16) ~ 0)
666 "Punt socket: Invalid client path: %s",
713 if (protocol != IP_PROTOCOL_UDP &&
716 "only UDP (%d), TCP (%d) and SCTP (%d) protocols are supported, got %d",
717 IP_PROTOCOL_UDP, IP_PROTOCOL_TCP,
720 if (ipv != (
u8) ~ 0 && ipv != 4 && ipv != 6)
723 if (port == (
u16) ~ 0)
725 if ((ipv == 4) || (ipv == (
u8) ~ 0))
727 if (protocol == IP_PROTOCOL_UDP)
729 else if (protocol == IP_PROTOCOL_TCP)
735 if ((ipv == 6) || (ipv == (
u8) ~ 0))
737 if (protocol == IP_PROTOCOL_UDP)
739 else if (protocol == IP_PROTOCOL_TCP)
752 "punt TCP/SCTP ports is not supported yet");
754 if (ipv == 4 || ipv == (
u8) ~ 0)
757 if (ipv == 6 || ipv == (
u8) ~ 0)
766 "punt TCP/SCTP ports is not supported yet");
767 if (ipv == 4 || ipv == (
u8) ~ 0)
770 if (ipv == 6 || ipv == (
u8) ~ 0)
793 else if (
unformat (input,
"%d", &port))
796 protocol = IP_PROTOCOL_UDP;
798 protocol = IP_PROTOCOL_TCP;
841 .short_help =
"set punt [udp|tcp] [del] <all | port-num1 [port-num2 ...]>",
846 #ifndef CLIB_MARCH_VARIANT 864 protocol = IP_PROTOCOL_UDP;
866 protocol = IP_PROTOCOL_TCP;
867 else if (
unformat (input,
"%d", &port))
869 else if (
unformat (input,
"socket %s", &socket_name))
881 (
char *) socket_name);
894 .path =
"punt socket register",
896 .short_help =
"punt socket register [ipv4|ipv6] [udp|tcp]> <all | port-num1 [port-num2 ...]> <socket>",
918 protocol = IP_PROTOCOL_UDP;
920 protocol = IP_PROTOCOL_TCP;
921 else if (
unformat (input,
"%d", &port))
944 .path =
"punt socket deregister",
946 .short_help =
"punt socket deregister [ipv4|ipv6] [udp|tcp]> <all | port-num1 [port-num2 ...]>",
964 if (pc && pc->
port != 0)
967 if (pc->
protocol == IP_PROTOCOL_UDP)
979 sizeof (pc->
caddr.sun_path));
991 u8 *is_ipv6 = va_arg (*args,
u8 *);
997 if (pc && pc->
port != 0)
1000 if (pc->
protocol == IP_PROTOCOL_UDP)
1006 s =
format (s,
" punt %s port %d to socket %s \n",
1007 (pc->
protocol == IP_PROTOCOL_UDP) ?
"UDP" :
"TCP",
1054 .path =
"show punt socket registrations",
1056 .short_help =
"show punt socket registrations [ipv4|ipv6]",
1076 "interface-output");
1087 char *socket_path = 0;
1091 if (
unformat (input,
"socket %s", &socket_path))
1092 strncpy (pm->
sun_path, socket_path, UNIX_PATH_MAX - 1);
1098 if (socket_path == 0)
1102 struct sockaddr_un addr;
1103 if ((pm->
socket_fd = socket (AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0)) == -1)
1109 addr.sun_family = AF_UNIX;
1110 if (*socket_path ==
'\0')
1112 *addr.sun_path =
'\0';
1113 strncpy (addr.sun_path + 1, socket_path + 1,
1114 sizeof (addr.sun_path) - 2);
1118 strncpy (addr.sun_path, socket_path, sizeof (addr.sun_path) - 1);
1119 unlink (socket_path);
1122 if (bind (pm->
socket_fd, (
struct sockaddr *) &addr, sizeof (addr)) == -1)
1131 template.file_descriptor = pm->
socket_fd;
1132 template.description =
format (0,
"%s", socket_path);
vlib_node_t * interface_output_node
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
static uword udp46_punt_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame, int is_ip4)
IPv4/IPv6 UDP punt node main loop.
static u32 vlib_get_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt)
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
vnet_main_t * vnet_get_main(void)
static clib_error_t * punt_config(vlib_main_t *vm, unformat_input_t *input)
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
static clib_error_t * punt_socket_read_ready(clib_file_t *uf)
static void vlib_node_set_interrupt_pending(vlib_main_t *vm, u32 node_index)
#define clib_memcpy_fast(a, b, c)
static punt_client_t * punt_client_get(bool is_ip4, u16 port)
u16 current_length
Nbytes between current data and the end of this buffer.
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
u8 * format_punt_socket(u8 *s, va_list *args)
clib_error_t * vnet_punt_add_del(vlib_main_t *vm, u8 ipv, u8 protocol, u16 port, bool is_add)
Request IP traffic punt to the local TCP/IP stack.
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
#define VLIB_NODE_FN(node)
punt_socket_detail_t * punt_socket_entries(u8 ipv)
vlib_error_t * errors
Vector of errors for this node.
#define foreach_punt_next
format_function_t format_vnet_sw_if_index_name
enum punt_action_e action
#define punt_next_punt(is_ip4)
clib_file_function_t * read_function
static void vlib_trace_buffer(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, vlib_buffer_t *b, int follow_chain)
#define VLIB_INIT_FUNCTION(x)
static uword udp46_punt_socket_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, bool is_ip4)
static clib_error_t * punt_cli(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define sparse_vec_validate(v, i)
#define clib_error_return(e, args...)
clib_file_main_t file_main
static struct sockaddr_un * punt_socket_get(bool is_ip4, u16 port)
punt_client_t * clients_by_dst_port6
static uword udp4_punt_socket(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
struct punt_trace_t_ punt_trace_t
vlib_error_t error
Error code for buffers to be enqueued to error handler.
void sctp_punt_unknown(vlib_main_t *vm, u8 is_ip4, u8 is_add)
clib_error_t * vnet_punt_socket_del(vlib_main_t *vm, bool is_ip4, u8 l4_protocol, u16 port)
vlib_node_registration_t udp4_punt_socket_node
(constructor) VLIB_REGISTER_NODE (udp4_punt_socket_node)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
static uword udp6_punt_socket(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
#define VLIB_CONFIG_FUNCTION(x, n,...)
#define vec_del1(v, i)
Delete the element at index I.
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
static uword punt_socket_rx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
static_always_inline u32 vlib_buffer_get_default_data_size(vlib_main_t *vm)
void udp_punt_unknown(vlib_main_t *vm, u8 is_ip4, u8 is_add)
#define VLIB_REGISTER_NODE(x,...)
static vlib_node_registration_t punt_socket_rx_node
(constructor) VLIB_REGISTER_NODE (punt_socket_rx_node)
void udp_unregister_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u8 is_ip4)
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
static clib_error_t * punt_socket_show_cmd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
enum punt_action_e action
#define VLIB_CLI_COMMAND(x,...)
static uword sparse_vec_index(void *v, uword sparse_index)
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
static uword clib_file_add(clib_file_main_t *um, clib_file_t *template)
char sun_path[sizeof(struct sockaddr_un)]
#define clib_error_report(e)
punt_client_t * clients_by_dst_port4
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
static clib_error_t * punt_socket_deregister_cmd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static vlib_main_t * vlib_get_main(void)
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
#define vec_elt(v, i)
Get vector value at index i.
static u8 * format_punt_trace(u8 *s, va_list *va)
struct _vlib_node_registration vlib_node_registration_t
void tcp_punt_unknown(vlib_main_t *vm, u8 is_ip4, u8 is_add)
vlib_node_registration_t udp6_punt_socket_node
(constructor) VLIB_REGISTER_NODE (udp6_punt_socket_node)
clib_error_t * vnet_punt_socket_add(vlib_main_t *vm, u32 header_version, bool is_ip4, u8 protocol, u16 port, char *client_pathname)
static u8 * format_udp_punt_trace(u8 *s, va_list *args)
bool udp_is_valid_dst_port(udp_dst_port_t dst_port, u8 is_ip4)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u32 next_buffer
Next buffer for this linked-list of buffers.
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
vlib_node_registration_t udp4_punt_node
(constructor) VLIB_REGISTER_NODE (udp4_punt_node)
VLIB buffer representation.
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
static int punt_socket_register(bool is_ip4, u8 protocol, u16 port, char *client_pathname)
#define VLIB_NODE_FLAG_IS_DROP
#define PUNT_PACKETDESC_VERSION
#define vec_foreach(var, vec)
Vector iterator.
static void punt_socket_unregister(bool is_ip4, u8 protocol, u16 port)
static char * punt_error_strings[]
clib_error_t * ip_punt_init(vlib_main_t *vm)
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
static clib_error_t * punt_socket_register_cmd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
vlib_node_registration_t udp6_punt_node
(constructor) VLIB_REGISTER_NODE (udp6_punt_node)
static void vlib_set_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt, u32 count)
static void * sparse_vec_new(uword elt_bytes, uword sparse_index_bits)
static uword punt_socket_rx_fd(vlib_main_t *vm, vlib_node_runtime_t *node, u32 fd)
static u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
char * vnet_punt_get_server_pathname(void)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definitions for punt infrastructure.
#define SPARSE_VEC_INVALID_INDEX