udp: support for disabling tx csum
Type: feature
Signed-off-by: Florin Coras <fcoras@cisco.com>
Change-Id: I84843eb3a0a66c64cd46536624633e0dae1c4681
diff --git a/src/vnet/udp/udp.c b/src/vnet/udp/udp.c
index c919c95..7851da8 100644
--- a/src/vnet/udp/udp.c
+++ b/src/vnet/udp/udp.c
@@ -194,6 +194,8 @@
else
listener->c_flags |= TRANSPORT_CONNECTION_F_CLESS;
clib_spinlock_init (&listener->rx_lock);
+ if (!um->csum_offload)
+ listener->cfg_flags |= UDP_CFG_F_NO_CSUM_OFFLOAD;
udp_connection_register_port (lcl_port_ho, lcl->is_ip4);
return listener->c_c_index;
@@ -225,7 +227,8 @@
always_inline u32
udp_push_one_header (vlib_main_t *vm, udp_connection_t *uc, vlib_buffer_t *b)
{
- vlib_buffer_push_udp (b, uc->c_lcl_port, uc->c_rmt_port, 1);
+ vlib_buffer_push_udp (b, uc->c_lcl_port, uc->c_rmt_port,
+ udp_csum_offload (uc));
b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
/* reuse tcp medatada for now */
vnet_buffer (b)->tcp.connection_index = uc->c_c_index;
@@ -405,6 +408,8 @@
clib_spinlock_init (&uc->rx_lock);
uc->c_flags |= TRANSPORT_CONNECTION_F_CLESS;
}
+ if (!um->csum_offload)
+ uc->cfg_flags |= UDP_CFG_F_NO_CSUM_OFFLOAD;
uc->next_node_index = rmt->next_node_index;
uc->next_node_opaque = rmt->next_node_opaque;
@@ -519,6 +524,7 @@
vlib_node_add_next (vm, udp6_local_node.index, udp6_input_node.index);
um->default_mtu = 1500;
+ um->csum_offload = 1;
return 0;
}
diff --git a/src/vnet/udp/udp.h b/src/vnet/udp/udp.h
index 96316a4..94362ad 100644
--- a/src/vnet/udp/udp.h
+++ b/src/vnet/udp/udp.h
@@ -55,6 +55,24 @@
#undef _
} udp_conn_flags_t;
+#define foreach_udp_cfg_flag _ (NO_CSUM_OFFLOAD, "no-csum-offload")
+
+typedef enum udp_cfg_flag_bits_
+{
+#define _(sym, str) UDP_CFG_F_##sym##_BIT,
+ foreach_udp_cfg_flag
+#undef _
+ UDP_CFG_N_FLAG_BITS
+} udp_cfg_flag_bits_e;
+
+typedef enum udp_cfg_flag_
+{
+#define _(sym, str) UDP_CFG_F_##sym = 1 << UDP_CFG_F_##sym##_BIT,
+ foreach_udp_cfg_flag
+#undef _
+ UDP_CFG_N_FLAGS
+} __clib_packed udp_cfg_flags_t;
+
typedef struct
{
/** Required for pool_get_aligned */
@@ -62,12 +80,15 @@
transport_connection_t connection; /**< must be first */
clib_spinlock_t rx_lock; /**< rx fifo lock */
u8 flags; /**< connection flags */
+ udp_cfg_flags_t cfg_flags; /**< configuration flags */
u16 mss; /**< connection mss */
u32 sw_if_index; /**< connection sw_if_index */
u32 next_node_index; /**< Can be used to control next node in output */
u32 next_node_opaque; /**< Opaque to pass to next node */
} udp_connection_t;
+#define udp_csum_offload(uc) (!((uc)->cfg_flags & UDP_CFG_F_NO_CSUM_OFFLOAD))
+
typedef struct
{
/* Name (a c string). */
@@ -122,6 +143,7 @@
u16 default_mtu;
u16 msg_id_base;
+ u8 csum_offload;
u8 icmp_send_unreachable_disabled;
} udp_main_t;
diff --git a/src/vnet/udp/udp_cli.c b/src/vnet/udp/udp_cli.c
index 9787eed..72dd9d8 100644
--- a/src/vnet/udp/udp_cli.c
+++ b/src/vnet/udp/udp_cli.c
@@ -38,6 +38,33 @@
return s;
}
+static const char *udp_cfg_flags_str[] = {
+#define _(sym, str) str,
+ foreach_udp_cfg_flag
+#undef _
+};
+
+static u8 *
+format_udp_cfg_flags (u8 *s, va_list *args)
+{
+ udp_connection_t *tc = va_arg (*args, udp_connection_t *);
+ int i, last = -1;
+
+ for (i = 0; i < UDP_CFG_N_FLAG_BITS; i++)
+ if (tc->cfg_flags & (1 << i))
+ last = i;
+ if (last >= 0)
+ s = format (s, " cfg: ");
+ for (i = 0; i < last; i++)
+ {
+ if (tc->cfg_flags & (1 << i))
+ s = format (s, "%s, ", udp_cfg_flags_str[i]);
+ }
+ if (last >= 0)
+ s = format (s, "%s", udp_cfg_flags_str[last]);
+ return s;
+}
+
static const char *udp_connection_flags_str[] = {
#define _(sym, str) str,
foreach_udp_connection_flag
@@ -68,8 +95,8 @@
{
udp_connection_t *uc = va_arg (*args, udp_connection_t *);
- s = format (s, " index %u flags: %U", uc->c_c_index,
- format_udp_connection_flags, uc);
+ s = format (s, " index %u%U flags: %U", uc->c_c_index, format_udp_cfg_flags,
+ uc, format_udp_connection_flags, uc);
if (!(uc->flags & UDP_CONN_F_LISTEN))
s = format (s, " \n sw_if_index: %d, mss: %u\n", uc->sw_if_index, uc->mss);
@@ -106,6 +133,8 @@
um->default_mtu = tmp;
else if (unformat (input, "icmp-unreachable-disabled"))
um->icmp_send_unreachable_disabled = 1;
+ else if (unformat (input, "no-csum-offload"))
+ um->csum_offload = 0;
else
return clib_error_return (0, "unknown input `%U'",
format_unformat_error, input);
diff --git a/src/vnet/udp/udp_input.c b/src/vnet/udp/udp_input.c
index c11c0d5..1c1d9e8 100644
--- a/src/vnet/udp/udp_input.c
+++ b/src/vnet/udp/udp_input.c
@@ -115,6 +115,7 @@
uc->c_fib_index = listener->c_fib_index;
uc->mss = listener->mss;
uc->flags |= UDP_CONN_F_CONNECTED;
+ uc->cfg_flags = listener->cfg_flags;
if (session_dgram_accept (&uc->connection, listener->c_s_index,
listener->c_thread_index))
diff --git a/src/vnet/udp/udp_output.c b/src/vnet/udp/udp_output.c
index 1252bfb..3ab21d3 100644
--- a/src/vnet/udp/udp_output.c
+++ b/src/vnet/udp/udp_output.c
@@ -81,7 +81,7 @@
{
if (uc->c_is_ip4)
vlib_buffer_push_ip4_custom (vm, b, &uc->c_lcl_ip4, &uc->c_rmt_ip4,
- IP_PROTOCOL_UDP, 1 /* csum offload */,
+ IP_PROTOCOL_UDP, udp_csum_offload (uc),
0 /* is_df */, uc->c_dscp);
else
vlib_buffer_push_ip6 (vm, b, &uc->c_lcl_ip6, &uc->c_rmt_ip6,