#include <vnet/ip/ip.h>
#include <vlib/vlib.h>
-#include <vnet/pg/pg.h>
#include <vnet/udp/udp.h>
#include <vnet/tcp/tcp.h>
#include <vnet/ip/punt.h>
ip_address_family_t af,
ip_protocol_t protocol, u16 port, bool is_add)
{
+ int is_ip4 = af == AF_IP4;
+
/* For now we only support TCP and UDP punt */
if (protocol != IP_PROTOCOL_UDP && protocol != IP_PROTOCOL_TCP)
return clib_error_return (0,
if (port == (u16) ~ 0)
{
if (protocol == IP_PROTOCOL_UDP)
- udp_punt_unknown (vm, af == AF_IP4, is_add);
+ udp_punt_unknown (vm, is_ip4, is_add);
else if (protocol == IP_PROTOCOL_TCP)
- tcp_punt_unknown (vm, af == AF_IP4, is_add);
+ tcp_punt_unknown (vm, is_ip4, is_add);
return 0;
}
else if (is_add)
{
+ const vlib_node_registration_t *punt_node =
+ is_ip4 ? &udp4_punt_node : &udp6_punt_node;
+
if (protocol == IP_PROTOCOL_TCP)
return clib_error_return (0, "punt TCP ports is not supported yet");
- udp_register_dst_port (vm, port, udp4_punt_node.index, af == AF_IP4);
+ udp_register_dst_port (vm, port, punt_node->index, is_ip4);
return 0;
}
if (protocol == IP_PROTOCOL_TCP)
return clib_error_return (0, "punt TCP ports is not supported yet");
- udp_unregister_dst_port (vm, port, af == AF_IP4);
+ udp_unregister_dst_port (vm, port, is_ip4);
return 0;
}
}
+/**
+ * @brief Request exception traffic punt.
+ *
+ * @param reason Punting reason
+ *
+ * @returns 0 on success, non-zero value otherwise
+ */
+static clib_error_t *
+punt_exception_add_del (vlib_punt_reason_t reason, bool is_add)
+{
+ punt_main_t *pm = &punt_main;
+ int rv = 0;
+ vnet_punt_reason_flag_t flag = vlib_punt_reason_get_flags (reason);
+ const char *node_name =
+ vnet_punt_reason_flag_is_IP6_PACKET (flag) ? "ip6-punt" : "ip4-punt";
+ if (is_add)
+ rv = vlib_punt_register (pm->hdl, reason, node_name);
+ else
+ rv = vlib_punt_unregister (pm->hdl, reason, node_name);
+ if (!rv)
+ return 0;
+ else
+ return clib_error_return (0, is_add ? "Existing punting registration..." :
+ "Punting registration not found...");
+}
+
clib_error_t *
vnet_punt_add_del (vlib_main_t * vm, const punt_reg_t * pr, bool is_add)
{
return (punt_l4_add_del (vm, pr->punt.l4.af, pr->punt.l4.protocol,
pr->punt.l4.port, is_add));
case PUNT_TYPE_EXCEPTION:
+ return punt_exception_add_del (pr->punt.exception.reason, is_add);
case PUNT_TYPE_IP_PROTO:
break;
}
static clib_error_t *
punt_cli (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
+ unformat_input_t * input__, vlib_cli_command_t * cmd)
{
+ unformat_input_t line_input, *input = &line_input;
clib_error_t *error = NULL;
bool is_add = true;
/* *INDENT-OFF* */
u32 port;
/* *INDENT-ON* */
+ if (!unformat_user (input__, unformat_line_input, input))
+ return 0;
+
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (input, "del"))
is_add = false;
+ else if (unformat (input, "reason %U", unformat_punt_reason,
+ &pr.punt.exception.reason))
+ pr.type = PUNT_TYPE_EXCEPTION;
else if (unformat (input, "ipv4"))
pr.punt.l4.af = AF_IP4;
else if (unformat (input, "ipv6"))
}
done:
+ unformat_free (input);
return error;
}
static clib_error_t *
punt_socket_register_cmd (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
+ unformat_input_t * input__,
+ vlib_cli_command_t * cmd)
{
+ unformat_input_t line_input, *input = &line_input;
u8 *socket_name = 0;
clib_error_t *error = NULL;
/* *INDENT-OFF* */
};
/* *INDENT-ON* */
+ if (!unformat_user (input__, unformat_line_input, input))
+ return 0;
+
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (input, "ipv4"))
pr.punt.l4.port = ~0;
else if (unformat (input, "socket %s", &socket_name))
;
+ else if (unformat (input, "reason %U", unformat_punt_reason,
+ &pr.punt.exception.reason))
+ pr.type = PUNT_TYPE_EXCEPTION;
else
{
error = clib_error_return (0, "parse error: '%U'",
error = vnet_punt_socket_add (vm, 1, &pr, (char *) socket_name);
done:
+ unformat_free (input);
return error;
}
static clib_error_t *
punt_socket_deregister_cmd (vlib_main_t * vm,
- unformat_input_t * input,
+ unformat_input_t * input__,
vlib_cli_command_t * cmd)
{
+ unformat_input_t line_input, *input = &line_input;
clib_error_t *error = NULL;
/* *INDENT-OFF* */
punt_reg_t pr = {
};
/* *INDENT-ON* */
+ if (!unformat_user (input__, unformat_line_input, input))
+ return 0;
+
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (input, "ipv4"))
;
else if (unformat (input, "all"))
pr.punt.l4.port = ~0;
+ else if (unformat (input, "reason %U", unformat_punt_reason,
+ &pr.punt.exception.reason))
+ pr.type = PUNT_TYPE_EXCEPTION;
else
{
error = clib_error_return (0, "parse error: '%U'",
error = vnet_punt_socket_del (vm, &pr);
done:
+ unformat_free (input);
return error;
}
static clib_error_t *
punt_socket_show_cmd (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
+ unformat_input_t * input__, vlib_cli_command_t * cmd)
{
+ unformat_input_t line_input, *input = &line_input;
clib_error_t *error = NULL;
punt_type_t pt;
pt = PUNT_TYPE_L4;
+ if (!unformat_user (input__, unformat_line_input, input))
+ return 0;
+
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (input, "exception"))
punt_client_walk (pt, punt_client_show_one, vm);
done:
+ unformat_free (input);
return (error);
}
return (error);
}
+u8 *
+format_vnet_punt_reason_flags (u8 *s, va_list *args)
+{
+ vnet_punt_reason_flag_t flag = va_arg (*args, int);
+#define _(pos, len, value, name, str) \
+ if (vnet_punt_reason_flag_is_##name (flag)) \
+ s = format (s, "%s ", str);
+
+ foreach_vnet_punt_reason_flag
+#undef _
+ return (s);
+}
+
VLIB_INIT_FUNCTION (ip_punt_init);
static clib_error_t *
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);
+ template.description = format (0, "punt socket %s", socket_path);
pm->clib_file_index = clib_file_add (fm, &template);
pm->is_configured = true;