ip: fix length calculation in ip6-receive
[vpp.git] / src / vnet / udp / udp.c
index 1a5621f..5f73e39 100644 (file)
@@ -16,7 +16,8 @@
 #include <vnet/udp/udp.h>
 #include <vnet/session/session.h>
 #include <vnet/dpo/load_balance.h>
-#include <vnet/fib/ip4_fib.h>
+#include <vnet/ip/ip4_inlines.h>
+#include <vnet/ip/ip6_inlines.h>
 #include <vppinfra/sparse_vec.h>
 
 udp_main_t udp_main;
@@ -115,7 +116,6 @@ udp_connection_alloc (u32 thread_index)
   uc->c_c_index = uc - um->connections[thread_index];
   uc->c_thread_index = thread_index;
   uc->c_proto = TRANSPORT_PROTO_UDP;
-  clib_spinlock_init (&uc->rx_lock);
   return uc;
 }
 
@@ -123,6 +123,7 @@ void
 udp_connection_free (udp_connection_t * uc)
 {
   u32 thread_index = uc->c_thread_index;
+  clib_spinlock_free (&uc->rx_lock);
   if (CLIB_DEBUG)
     clib_memset (uc, 0xFA, sizeof (*uc));
   pool_put (udp_main.connections[thread_index], uc);
@@ -221,6 +222,7 @@ udp_session_unbind (u32 listener_index)
   listener = udp_listener_get (listener_index);
   udp_connection_unregister_port (clib_net_to_host_u16 (listener->c_lcl_port),
                                  listener->c_is_ip4);
+  clib_spinlock_free (&listener->rx_lock);
   pool_put (um->listener_pool, listener);
   return 0;
 }
@@ -234,19 +236,14 @@ udp_session_get_listener (u32 listener_index)
   return &us->connection;
 }
 
-static u32
-udp_push_header (transport_connection_t * tc, vlib_buffer_t * b)
+always_inline u32
+udp_push_one_header (vlib_main_t *vm, udp_connection_t *uc, vlib_buffer_t *b)
 {
-  udp_connection_t *uc;
-  vlib_main_t *vm = vlib_get_main ();
-
-  uc = udp_get_connection_from_transport (tc);
-
   vlib_buffer_push_udp (b, uc->c_lcl_port, uc->c_rmt_port, 1);
-  if (tc->is_ip4)
+  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 */ ,
-                                0 /* is_df */ );
+                                IP_PROTOCOL_UDP, 1 /* csum offload */,
+                                0 /* is_df */, uc->c_dscp);
   else
     vlib_buffer_push_ip6 (vm, b, &uc->c_lcl_ip6, &uc->c_rmt_ip6,
                          IP_PROTOCOL_UDP);
@@ -254,6 +251,39 @@ udp_push_header (transport_connection_t * tc, vlib_buffer_t * b)
   vnet_buffer (b)->sw_if_index[VLIB_TX] = uc->c_fib_index;
   b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
 
+  return 0;
+}
+
+static u32
+udp_push_header (transport_connection_t *tc, vlib_buffer_t **bs, u32 n_bufs)
+{
+  vlib_main_t *vm = vlib_get_main ();
+  udp_connection_t *uc;
+
+  uc = udp_connection_from_transport (tc);
+
+  while (n_bufs >= 4)
+    {
+      vlib_prefetch_buffer_header (bs[2], STORE);
+      vlib_prefetch_buffer_header (bs[3], STORE);
+
+      udp_push_one_header (vm, uc, bs[0]);
+      udp_push_one_header (vm, uc, bs[1]);
+
+      n_bufs -= 2;
+      bs += 2;
+    }
+  while (n_bufs)
+    {
+      if (n_bufs > 1)
+       vlib_prefetch_buffer_header (bs[1], STORE);
+
+      udp_push_one_header (vm, uc, bs[0]);
+
+      n_bufs -= 1;
+      bs += 1;
+    }
+
   if (PREDICT_FALSE (uc->flags & UDP_CONN_F_CLOSING))
     {
       if (!transport_max_tx_dequeue (&uc->connection))
@@ -279,7 +309,7 @@ udp_session_close (u32 connection_index, u32 thread_index)
   udp_connection_t *uc;
 
   uc = udp_connection_get (connection_index, thread_index);
-  if (!uc)
+  if (!uc || (uc->flags & UDP_CONN_F_MIGRATED))
     return;
 
   if (!transport_max_tx_dequeue (&uc->connection))
@@ -307,7 +337,7 @@ udp_session_send_params (transport_connection_t * tconn,
 {
   udp_connection_t *uc;
 
-  uc = udp_get_connection_from_transport (tconn);
+  uc = udp_connection_from_transport (tconn);
 
   /* No constraint on TX window */
   sp->snd_space = ~0;
@@ -373,8 +403,7 @@ conn_alloc:
   udp_connection_register_port (vm, lcl_port, rmt->is_ip4);
 
   /* We don't poll main thread if we have workers */
-  if (vlib_num_workers ())
-    thread_index = 1;
+  thread_index = transport_cl_thread ();
 
   uc = udp_connection_alloc (thread_index);
   ip_copy (&uc->c_rmt_ip, &rmt->ip, rmt->is_ip4);
@@ -384,12 +413,18 @@ conn_alloc:
   uc->c_is_ip4 = rmt->is_ip4;
   uc->c_proto = TRANSPORT_PROTO_UDP;
   uc->c_fib_index = rmt->fib_index;
+  uc->c_dscp = rmt->dscp;
   uc->mss = rmt->mss ? rmt->mss : udp_default_mtu (um, uc->c_is_ip4);
   uc->flags |= UDP_CONN_F_OWNS_PORT;
   if (rmt->transport_flags & TRANSPORT_CFG_F_CONNECTED)
-    uc->flags |= UDP_CONN_F_CONNECTED;
+    {
+      uc->flags |= UDP_CONN_F_CONNECTED;
+    }
   else
-    uc->c_flags |= TRANSPORT_CONNECTION_F_CLESS;
+    {
+      clib_spinlock_init (&uc->rx_lock);
+      uc->c_flags |= TRANSPORT_CONNECTION_F_CLESS;
+    }
 
   return uc->c_c_index;
 }
@@ -401,7 +436,7 @@ udp_session_get_half_open (u32 conn_index)
   u32 thread_index;
 
   /* We don't poll main thread if we have workers */
-  thread_index = vlib_num_workers ()? 1 : 0;
+  thread_index = transport_cl_thread ();
   uc = udp_connection_get (conn_index, thread_index);
   if (!uc)
     return 0;
@@ -463,62 +498,6 @@ static const transport_proto_vft_t udp_proto = {
 };
 /* *INDENT-ON* */
 
-int
-udpc_connection_open (transport_endpoint_cfg_t * rmt)
-{
-  udp_connection_t *uc;
-  /* Reproduce the logic of udp_open_connection to find the correct thread */
-  u32 thread_index = vlib_num_workers ()? 1 : vlib_get_main ()->thread_index;
-  u32 uc_index;
-  uc_index = udp_open_connection (rmt);
-  if (uc_index == (u32) ~ 0)
-    return -1;
-  uc = udp_connection_get (uc_index, thread_index);
-  uc->flags |= UDP_CONN_F_CONNECTED;
-  return uc_index;
-}
-
-u32
-udpc_connection_listen (u32 session_index, transport_endpoint_t * lcl)
-{
-  udp_connection_t *listener;
-  u32 li_index;
-  li_index = udp_session_bind (session_index, lcl);
-  if (li_index == (u32) ~ 0)
-    return -1;
-  listener = udp_listener_get (li_index);
-  listener->flags |= UDP_CONN_F_CONNECTED;
-  /* Fake udp listener, i.e., make sure session layer adds a udp instead of
-   * udpc listener to the lookup table */
-  ((session_endpoint_cfg_t *) lcl)->transport_proto = TRANSPORT_PROTO_UDP;
-  return li_index;
-}
-
-/* *INDENT-OFF* */
-static const transport_proto_vft_t udpc_proto = {
-  .start_listen = udpc_connection_listen,
-  .stop_listen = udp_session_unbind,
-  .connect = udpc_connection_open,
-  .push_header = udp_push_header,
-  .get_connection = udp_session_get,
-  .get_listener = udp_session_get_listener,
-  .get_half_open = udp_session_get_half_open,
-  .close = udp_session_close,
-  .cleanup = udp_session_cleanup,
-  .send_params = udp_session_send_params,
-  .format_connection = format_udp_session,
-  .format_half_open = format_udp_half_open_session,
-  .format_listener = format_udp_listener_session,
-  .transport_options = {
-    .name = "udpc",
-    .short_name = "U",
-    .tx_type = TRANSPORT_TX_DGRAM,
-    .service_type = TRANSPORT_SERVICE_VC,
-    .half_open_has_fifos = 1
-  },
-};
-/* *INDENT-ON* */
-
 static clib_error_t *
 udp_init (vlib_main_t * vm)
 {
@@ -545,10 +524,6 @@ udp_init (vlib_main_t * vm)
                               FIB_PROTOCOL_IP4, ip4_lookup_node.index);
   transport_register_protocol (TRANSPORT_PROTO_UDP, &udp_proto,
                               FIB_PROTOCOL_IP6, ip6_lookup_node.index);
-  transport_register_protocol (TRANSPORT_PROTO_UDPC, &udpc_proto,
-                              FIB_PROTOCOL_IP4, ip4_lookup_node.index);
-  transport_register_protocol (TRANSPORT_PROTO_UDPC, &udpc_proto,
-                              FIB_PROTOCOL_IP6, ip6_lookup_node.index);
 
   /*
    * Initialize data structures