diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/vnet/udp/udp.c | 8 | ||||
-rw-r--r-- | src/vnet/udp/udp.h | 22 | ||||
-rw-r--r-- | src/vnet/udp/udp_cli.c | 33 | ||||
-rw-r--r-- | src/vnet/udp/udp_input.c | 1 | ||||
-rw-r--r-- | src/vnet/udp/udp_output.c | 2 |
5 files changed, 62 insertions, 4 deletions
diff --git a/src/vnet/udp/udp.c b/src/vnet/udp/udp.c index c919c958254..7851da8e91b 100644 --- a/src/vnet/udp/udp.c +++ b/src/vnet/udp/udp.c @@ -194,6 +194,8 @@ udp_session_bind (u32 session_index, transport_endpoint_cfg_t *lcl) 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 @@ udp_session_get_listener (u32 listener_index) 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 @@ conn_alloc: 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 @@ udp_init (vlib_main_t * vm) 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 96316a43fc8..94362ad991c 100644 --- a/src/vnet/udp/udp.h +++ b/src/vnet/udp/udp.h @@ -55,6 +55,24 @@ typedef enum udp_conn_flags_ #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 @@ typedef struct 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 @@ typedef struct 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 9787eedf933..72dd9d8447d 100644 --- a/src/vnet/udp/udp_cli.c +++ b/src/vnet/udp/udp_cli.c @@ -38,6 +38,33 @@ format_udp_connection_id (u8 * s, va_list * args) 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 @@ format_udp_vars (u8 * s, va_list * args) { 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 @@ udp_config_fn (vlib_main_t * vm, unformat_input_t * input) 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 c11c0d51214..1c1d9e8e645 100644 --- a/src/vnet/udp/udp_input.c +++ b/src/vnet/udp/udp_input.c @@ -115,6 +115,7 @@ udp_connection_accept (udp_connection_t * listener, session_dgram_hdr_t * hdr, 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 1252bfb3bad..3ab21d32270 100644 --- a/src/vnet/udp/udp_output.c +++ b/src/vnet/udp/udp_output.c @@ -81,7 +81,7 @@ udp_output_push_ip (vlib_main_t *vm, vlib_buffer_t *b, udp_connection_t *uc, { 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, |