udp: support for disabling tx csum 78/37478/2
authorFlorin Coras <fcoras@cisco.com>
Wed, 19 Oct 2022 01:37:56 +0000 (18:37 -0700)
committerDave Wallace <dwallacelf@gmail.com>
Thu, 20 Oct 2022 18:14:32 +0000 (18:14 +0000)
Type: feature

Signed-off-by: Florin Coras <fcoras@cisco.com>
Change-Id: I84843eb3a0a66c64cd46536624633e0dae1c4681

src/vnet/udp/udp.c
src/vnet/udp/udp.h
src/vnet/udp/udp_cli.c
src/vnet/udp/udp_input.c
src/vnet/udp/udp_output.c

index c919c95..7851da8 100644 (file)
@@ -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;
 }
 
index 96316a4..94362ad 100644 (file)
@@ -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;
index 9787eed..72dd9d8 100644 (file)
@@ -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);
index c11c0d5..1c1d9e8 100644 (file)
@@ -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))
index 1252bfb..3ab21d3 100644 (file)
@@ -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,