X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=src%2Fvnet%2Fip%2Fpunt.c;h=6e2fcebf69e437a764815e5ff872044912b35336;hb=381735028c1bd7500279df3f168d8cac3c10a465;hp=568350cda82ea817103c5458f6a1cb2bc1078a28;hpb=1b708845633f7ddb816f81aed82f55fd9522fbcf;p=vpp.git diff --git a/src/vnet/ip/punt.c b/src/vnet/ip/punt.c index 568350cda82..6e2fcebf69e 100644 --- a/src/vnet/ip/punt.c +++ b/src/vnet/ip/punt.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -34,13 +35,12 @@ #include #include #include -#include #include #include -#include #define foreach_punt_next \ - _ (PUNT, "error-punt") + _ (PUNT4, "ip4-punt") \ + _ (PUNT6, "ip6-punt") typedef enum { @@ -58,6 +58,8 @@ enum punt_socket_rx_next_e PUNT_SOCKET_RX_N_NEXT }; +#define punt_next_punt(is_ip4) (is_ip4 ? PUNT_NEXT_PUNT4 : PUNT_NEXT_PUNT6) + vlib_node_registration_t udp4_punt_node; vlib_node_registration_t udp6_punt_node; vlib_node_registration_t udp4_punt_socket_node; @@ -104,7 +106,8 @@ udp46_punt_inline (vlib_main_t * vm, { u32 n_left_to_next; - vlib_get_next_frame (vm, node, PUNT_NEXT_PUNT, to_next, n_left_to_next); + vlib_get_next_frame (vm, node, punt_next_punt (is_ip4), to_next, + n_left_to_next); while (n_left_from > 0 && n_left_to_next > 0) { @@ -123,7 +126,7 @@ udp46_punt_inline (vlib_main_t * vm, b0->error = node->errors[PUNT_ERROR_UDP_PORT]; } - vlib_put_next_frame (vm, node, PUNT_NEXT_PUNT, n_left_to_next); + vlib_put_next_frame (vm, node, punt_next_punt (is_ip4), n_left_to_next); } return from_frame->n_vectors; @@ -256,7 +259,7 @@ punt_socket_get (bool is_ip4, u16 port) return NULL; } -static void +static int punt_socket_register (bool is_ip4, u8 protocol, u16 port, char *client_pathname) { @@ -265,12 +268,18 @@ punt_socket_register (bool is_ip4, u8 protocol, u16 port, punt_client_t *v = is_ip4 ? pm->clients_by_dst_port4 : pm->clients_by_dst_port6; - memset (&c, 0, sizeof (c)); + if (strncmp (client_pathname, vnet_punt_get_server_pathname (), + UNIX_PATH_MAX) == 0) + return -1; + + clib_memset (&c, 0, sizeof (c)); memcpy (c.caddr.sun_path, client_pathname, sizeof (c.caddr.sun_path)); c.caddr.sun_family = AF_UNIX; c.port = port; + c.protocol = protocol; n = sparse_vec_validate (v, port); n[0] = c; + return 0; } /* $$$$ Just leaves the mapping in place for now */ @@ -307,7 +316,7 @@ udp46_punt_socket_inline (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame, bool is_ip4) { - u32 *buffers = vlib_frame_args (frame); + u32 *buffers = vlib_frame_vector_args (frame); uword n_packets = frame->n_vectors; struct iovec *iovecs = 0; punt_main_t *pm = &punt_main; @@ -363,7 +372,7 @@ udp46_punt_socket_inline (vlib_main_t * vm, c = punt_client_get (is_ip4, port); udp_punt_trace_t *t; t = vlib_add_trace (vm, node, b, sizeof (t[0])); - clib_memcpy (&t->client, c, sizeof (t->client)); + clib_memcpy_fast (&t->client, c, sizeof (t->client)); } /* Re-set iovecs if present. */ @@ -396,7 +405,7 @@ udp46_punt_socket_inline (vlib_main_t * vm, } udp_punt_trace_t *t; t = vlib_add_trace (vm, node, b, sizeof (t[0])); - clib_memcpy (&t->client, c, sizeof (t->client)); + clib_memcpy_fast (&t->client, c, sizeof (t->client)); t->is_midchain = 1; } @@ -419,6 +428,9 @@ udp46_punt_socket_inline (vlib_main_t * vm, if (sendmsg (pm->socket_fd, &msg, 0) < (ssize_t) l) vlib_node_increment_counter (vm, node_index, PUNT_ERROR_SOCKET_TX_ERROR, 1); + else + vlib_node_increment_counter (vm, node_index, PUNT_ERROR_SOCKET_TX, 1); + } error: @@ -485,7 +497,7 @@ format_punt_trace (u8 * s, va_list * va) static uword punt_socket_rx_fd (vlib_main_t * vm, vlib_node_runtime_t * node, u32 fd) { - const uword buffer_size = VLIB_BUFFER_DATA_SIZE; + const uword buffer_size = vlib_buffer_get_default_data_size (vm); u32 n_trace = vlib_get_trace_count (vm, node); u32 next = node->cached_next_index; u32 n_left_to_next, next_index; @@ -592,17 +604,25 @@ punt_socket_rx (vlib_main_t * vm, return total_count; } +/* *INDENT-OFF* */ VLIB_REGISTER_NODE (punt_socket_rx_node, static) = { - .function = punt_socket_rx,.name = "punt-socket-rx",.type = - VLIB_NODE_TYPE_INPUT,.state = VLIB_NODE_STATE_INTERRUPT,.vector_size = - 1,.n_errors = PUNT_N_ERROR,.error_strings = - punt_error_strings,.n_next_nodes = PUNT_SOCKET_RX_N_NEXT,.next_nodes = - { -[PUNT_SOCKET_RX_NEXT_INTERFACE_OUTPUT] = "interface-output", - [PUNT_SOCKET_RX_NEXT_IP4_LOOKUP] = "ip4-lookup", - [PUNT_SOCKET_RX_NEXT_IP6_LOOKUP] = "ip6-lookup",},.format_trace = - format_punt_trace,}; + .function = punt_socket_rx, + .name = "punt-socket-rx", + .type = VLIB_NODE_TYPE_INPUT, + .state = VLIB_NODE_STATE_INTERRUPT, + .vector_size = 1, + .n_errors = PUNT_N_ERROR, + .error_strings = punt_error_strings, + .n_next_nodes = PUNT_SOCKET_RX_N_NEXT, + .next_nodes = { + [PUNT_SOCKET_RX_NEXT_INTERFACE_OUTPUT] = "interface-output", + [PUNT_SOCKET_RX_NEXT_IP4_LOOKUP] = "ip4-lookup", + [PUNT_SOCKET_RX_NEXT_IP6_LOOKUP] = "ip6-lookup", + }, + .format_trace = format_punt_trace, +}; +/* *INDENT-ON* */ static clib_error_t * punt_socket_read_ready (clib_file_t * uf) @@ -640,7 +660,10 @@ vnet_punt_socket_add (vlib_main_t * vm, u32 header_version, return clib_error_return (0, "UDP port number required"); /* Register client */ - punt_socket_register (is_ip4, protocol, port, client_pathname); + if (punt_socket_register (is_ip4, protocol, port, client_pathname) < 0) + return clib_error_return (0, + "Punt socket: Invalid client path: %s", + client_pathname); u32 node_index = is_ip4 ? udp4_punt_socket_node.index : udp6_punt_socket_node.index; @@ -685,11 +708,13 @@ vnet_punt_add_del (vlib_main_t * vm, u8 ipv, u8 protocol, u16 port, bool is_add) { - /* For now we only support UDP punt */ - if (protocol != IP_PROTOCOL_UDP && protocol != IP_PROTOCOL_TCP) + /* For now we only support TCP, UDP and SCTP punt */ + if (protocol != IP_PROTOCOL_UDP && + protocol != IP_PROTOCOL_TCP && protocol != IP_PROTOCOL_SCTP) return clib_error_return (0, - "only UDP (%d) and TCP (%d) protocols are supported, got %d", - IP_PROTOCOL_UDP, IP_PROTOCOL_TCP, protocol); + "only UDP (%d), TCP (%d) and SCTP (%d) protocols are supported, got %d", + IP_PROTOCOL_UDP, IP_PROTOCOL_TCP, + IP_PROTOCOL_SCTP, protocol); if (ipv != (u8) ~ 0 && ipv != 4 && ipv != 6) return clib_error_return (0, "IP version must be 4 or 6, got %d", ipv); @@ -702,6 +727,8 @@ vnet_punt_add_del (vlib_main_t * vm, u8 ipv, u8 protocol, u16 port, udp_punt_unknown (vm, 1, is_add); else if (protocol == IP_PROTOCOL_TCP) tcp_punt_unknown (vm, 1, is_add); + else if (protocol == IP_PROTOCOL_SCTP) + sctp_punt_unknown (vm, 1, is_add); } if ((ipv == 6) || (ipv == (u8) ~ 0)) @@ -710,6 +737,8 @@ vnet_punt_add_del (vlib_main_t * vm, u8 ipv, u8 protocol, u16 port, udp_punt_unknown (vm, 0, is_add); else if (protocol == IP_PROTOCOL_TCP) tcp_punt_unknown (vm, 0, is_add); + else if (protocol == IP_PROTOCOL_SCTP) + sctp_punt_unknown (vm, 0, is_add); } return 0; @@ -717,8 +746,9 @@ vnet_punt_add_del (vlib_main_t * vm, u8 ipv, u8 protocol, u16 port, else if (is_add) { - if (protocol == IP_PROTOCOL_TCP) - return clib_error_return (0, "punt TCP ports is not supported yet"); + if (protocol == IP_PROTOCOL_TCP || protocol == IP_PROTOCOL_SCTP) + return clib_error_return (0, + "punt TCP/SCTP ports is not supported yet"); if (ipv == 4 || ipv == (u8) ~ 0) udp_register_dst_port (vm, port, udp4_punt_node.index, 1); @@ -729,14 +759,25 @@ vnet_punt_add_del (vlib_main_t * vm, u8 ipv, u8 protocol, u16 port, return 0; } else - return clib_error_return (0, "punt delete is not supported yet"); + { + if (protocol == IP_PROTOCOL_TCP || protocol == IP_PROTOCOL_SCTP) + return clib_error_return (0, + "punt TCP/SCTP ports is not supported yet"); + if (ipv == 4 || ipv == (u8) ~ 0) + udp_unregister_dst_port (vm, port, 1); + + if (ipv == 6 || ipv == (u8) ~ 0) + udp_unregister_dst_port (vm, port, 0); + + return 0; + } } static clib_error_t * punt_cli (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { - u32 port; + u32 port = ~0; bool is_add = true; u32 protocol = ~0; clib_error_t *error = NULL; @@ -746,25 +787,9 @@ punt_cli (vlib_main_t * vm, if (unformat (input, "del")) is_add = false; else if (unformat (input, "all")) - { - /* punt both IPv6 and IPv4 when used in CLI */ - error = vnet_punt_add_del (vm, ~0, protocol, ~0, is_add); - if (error) - { - clib_error_report (error); - goto done; - } - } + ; else if (unformat (input, "%d", &port)) - { - /* punt both IPv6 and IPv4 when used in CLI */ - error = vnet_punt_add_del (vm, ~0, protocol, port, is_add); - if (error) - { - clib_error_report (error); - goto done; - } - } + ; else if (unformat (input, "udp")) protocol = IP_PROTOCOL_UDP; else if (unformat (input, "tcp")) @@ -776,6 +801,15 @@ punt_cli (vlib_main_t * vm, goto done; } } + + /* punt both IPv6 and IPv4 when used in CLI */ + error = vnet_punt_add_del (vm, ~0, protocol, port, is_add); + if (error) + { + clib_error_report (error); + goto done; + } + done: return error; } @@ -808,6 +842,228 @@ VLIB_CLI_COMMAND (punt_command, static) = { }; /* *INDENT-ON* */ +static clib_error_t * +punt_socket_register_cmd (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + bool is_ipv4 = true; + u32 protocol = ~0; + u32 port = ~0; + u8 *socket_name = 0; + clib_error_t *error = NULL; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "ipv4")) + ; + else if (unformat (input, "ipv6")) + is_ipv4 = false; + else if (unformat (input, "udp")) + protocol = IP_PROTOCOL_UDP; + else if (unformat (input, "tcp")) + protocol = IP_PROTOCOL_TCP; + else if (unformat (input, "%d", &port)) + ; + else if (unformat (input, "socket %s", &socket_name)) + ; + else + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, input); + goto done; + } + } + + error = + vnet_punt_socket_add (vm, 1, is_ipv4, protocol, port, + (char *) socket_name); + if (error) + { + goto done; + } +done: + return error; +} + +/*? + * + * @cliexpar + * @cliexcmd{punt socket register} + ?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (punt_socket_register_command, static) = +{ + .path = "punt socket register", + .function = punt_socket_register_cmd, + .short_help = "punt socket register [ipv4|ipv6] [udp|tcp]> ", + .is_mp_safe = 1, +}; +/* *INDENT-ON* */ + +static clib_error_t * +punt_socket_deregister_cmd (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + bool is_ipv4 = true; + u32 protocol = ~0; + u32 port = ~0; + clib_error_t *error = NULL; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "ipv4")) + ; + else if (unformat (input, "ipv6")) + is_ipv4 = false; + else if (unformat (input, "udp")) + protocol = IP_PROTOCOL_UDP; + else if (unformat (input, "tcp")) + protocol = IP_PROTOCOL_TCP; + else if (unformat (input, "%d", &port)) + ; + else + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, input); + goto done; + } + } + + error = vnet_punt_socket_del (vm, is_ipv4, protocol, port); + if (error) + { + goto done; + } +done: + return error; +} + +/*? + * + * @cliexpar + * @cliexcmd{punt socket register} + ?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (punt_socket_deregister_command, static) = +{ + .path = "punt socket deregister", + .function = punt_socket_deregister_cmd, + .short_help = "punt socket deregister [ipv4|ipv6] [udp|tcp]> ", + .is_mp_safe = 1, +}; +/* *INDENT-ON* */ + +punt_socket_detail_t * +punt_socket_entries (u8 ipv) +{ + punt_main_t *pm = &punt_main; + punt_client_t *pc; + punt_socket_detail_t *ps = 0; + bool is_valid; + + punt_client_t *v = !ipv ? pm->clients_by_dst_port4 : + pm->clients_by_dst_port6; + + vec_foreach (pc, v) + { + if (pc && pc->port != 0) + { + is_valid = false; + if (pc->protocol == IP_PROTOCOL_UDP) + { + is_valid = udp_is_valid_dst_port (pc->port, !ipv); + } + if (is_valid) + { + punt_socket_detail_t detail = { + .ipv = ipv, + .l4_protocol = pc->protocol, + .l4_port = pc->port + }; + memcpy (detail.pathname, pc->caddr.sun_path, + sizeof (pc->caddr.sun_path)); + vec_add1 (ps, detail); + } + } + } + return ps; +} + +u8 * +format_punt_socket (u8 * s, va_list * args) +{ + punt_client_t *clients = va_arg (*args, punt_client_t *); + u8 *is_ipv6 = va_arg (*args, u8 *); + punt_client_t *pc; + bool is_valid; + + vec_foreach (pc, clients) + { + if (pc && pc->port != 0) + { + is_valid = false; + if (pc->protocol == IP_PROTOCOL_UDP) + { + is_valid = udp_is_valid_dst_port (pc->port, !(*is_ipv6)); + } + if (is_valid) + { + s = format (s, " punt %s port %d to socket %s \n", + (pc->protocol == IP_PROTOCOL_UDP) ? "UDP" : "TCP", + pc->port, pc->caddr.sun_path); + } + } + } + + return (s); +} + +static clib_error_t * +punt_socket_show_cmd (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + u8 is_ipv6; + punt_main_t *pm = &punt_main; + clib_error_t *error = NULL; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "ipv4")) + is_ipv6 = 0; + else if (unformat (input, "ipv6")) + is_ipv6 = 1; + else + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, input); + goto done; + } + } + + punt_client_t *v = + is_ipv6 ? pm->clients_by_dst_port6 : pm->clients_by_dst_port4; + vlib_cli_output (vm, "%U", format_punt_socket, v, &is_ipv6); + +done: + return (error); +} + +/*? + * + * @cliexpar + * @cliexcmd{show punt socket ipv4} + ?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (show_punt_socket_registration_command, static) = +{ + .path = "show punt socket registrations", + .function = punt_socket_show_cmd, + .short_help = "show punt socket registrations [ipv4|ipv6]", + .is_mp_safe = 1, +}; +/* *INDENT-ON* */ + clib_error_t * punt_init (vlib_main_t * vm) { @@ -838,7 +1094,7 @@ punt_config (vlib_main_t * vm, unformat_input_t * input) while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "socket %s", &socket_path)) - strncpy (pm->sun_path, socket_path, 108 - 1); + strncpy (pm->sun_path, socket_path, UNIX_PATH_MAX - 1); else return clib_error_return (0, "unknown input `%U'", format_unformat_error, input); @@ -854,7 +1110,7 @@ punt_config (vlib_main_t * vm, unformat_input_t * input) return clib_error_return (0, "socket error"); } - memset (&addr, 0, sizeof (addr)); + clib_memset (&addr, 0, sizeof (addr)); addr.sun_family = AF_UNIX; if (*socket_path == '\0') { @@ -878,6 +1134,7 @@ punt_config (vlib_main_t * vm, unformat_input_t * input) clib_file_t template = { 0 }; template.read_function = punt_socket_read_ready; template.file_descriptor = pm->socket_fd; + template.description = format (0, "%s", socket_path); pm->clib_file_index = clib_file_add (fm, &template); pm->is_configured = true;