fix show session verbose crash with quic transport
[vpp.git] / src / plugins / quic / quic.c
index 4630689..ca48a90 100644 (file)
@@ -59,6 +59,53 @@ static void quic_transfer_connection (u32 ctx_index, u32 dest_thread);
 #define QUICLY_PACKET_TYPE_BITMASK 0xf0
 #define QUIC_FIFO_SIZE (64 << 10)
 
+#define QUIC_ERROR_FULL_FIFO 0xff10
+
+static char *
+quic_format_err (u64 code)
+{
+  switch (code)
+    {
+    case QUIC_ERROR_FULL_FIFO:
+      return "full fifo";
+    case QUICLY_ERROR_PACKET_IGNORED:
+      return "QUICLY_ERROR_PACKET_IGNORED";
+    case QUICLY_ERROR_SENDBUF_FULL:
+      return "QUICLY_ERROR_SENDBUF_FULL";
+    case QUICLY_ERROR_FREE_CONNECTION:
+      return "no open stream on connection";
+    case QUICLY_ERROR_RECEIVED_STATELESS_RESET:
+      return "QUICLY_ERROR_RECEIVED_STATELESS_RESET";
+    case QUICLY_TRANSPORT_ERROR_NONE:
+      return "QUICLY_TRANSPORT_ERROR_NONE";
+    case QUICLY_TRANSPORT_ERROR_INTERNAL:
+      return "QUICLY_TRANSPORT_ERROR_INTERNAL";
+    case QUICLY_TRANSPORT_ERROR_SERVER_BUSY:
+      return "QUICLY_TRANSPORT_ERROR_SERVER_BUSY";
+    case QUICLY_TRANSPORT_ERROR_FLOW_CONTROL:
+      return "QUICLY_TRANSPORT_ERROR_FLOW_CONTROL";
+    case QUICLY_TRANSPORT_ERROR_STREAM_ID:
+      return "QUICLY_TRANSPORT_ERROR_STREAM_ID";
+    case QUICLY_TRANSPORT_ERROR_STREAM_STATE:
+      return "QUICLY_TRANSPORT_ERROR_STREAM_STATE";
+    case QUICLY_TRANSPORT_ERROR_FINAL_OFFSET:
+      return "QUICLY_TRANSPORT_ERROR_FINAL_OFFSET";
+    case QUICLY_TRANSPORT_ERROR_FRAME_ENCODING:
+      return "QUICLY_TRANSPORT_ERROR_FRAME_ENCODING";
+    case QUICLY_TRANSPORT_ERROR_TRANSPORT_PARAMETER:
+      return "QUICLY_TRANSPORT_ERROR_TRANSPORT_PARAMETER";
+    case QUICLY_TRANSPORT_ERROR_VERSION_NEGOTIATION:
+      return "QUICLY_TRANSPORT_ERROR_VERSION_NEGOTIATION";
+    case QUICLY_TRANSPORT_ERROR_PROTOCOL_VIOLATION:
+      return "QUICLY_TRANSPORT_ERROR_PROTOCOL_VIOLATION";
+    case QUICLY_TRANSPORT_ERROR_INVALID_MIGRATION:
+      return "QUICLY_TRANSPORT_ERROR_INVALID_MIGRATION";
+    case QUICLY_TRANSPORT_ERROR_TLS_ALERT_BASE:
+      return "QUICLY_TRANSPORT_ERROR_TLS_ALERT_BASE";
+    default:
+      return "unknown error";
+    }
+}
 
 static u32
 quic_ctx_alloc (u32 thread_index)
@@ -137,7 +184,7 @@ quic_send_datagram (session_t * udp_session, quicly_datagram_t * packet)
   if (max_enqueue <= sizeof (session_dgram_hdr_t))
     {
       QUIC_DBG (1, "Not enough space to enqueue header");
-      return 1;
+      return QUIC_ERROR_FULL_FIFO;
     }
 
   max_enqueue -= sizeof (session_dgram_hdr_t);
@@ -146,7 +193,7 @@ quic_send_datagram (session_t * udp_session, quicly_datagram_t * packet)
     {
       QUIC_DBG (1, "Too much data to send, max_enqueue %u, len %u",
                max_enqueue, len);
-      return 1;
+      return QUIC_ERROR_FULL_FIFO;
     }
 
   /*  Build packet header for fifo */
@@ -176,13 +223,13 @@ quic_send_datagram (session_t * udp_session, quicly_datagram_t * packet)
   if (ret != sizeof (hdr))
     {
       QUIC_DBG (1, "Not enough space to enqueue header");
-      return 1;
+      return QUIC_ERROR_FULL_FIFO;
     }
   ret = svm_fifo_enqueue (f, len, packet->data.base);
   if (ret != len)
     {
       QUIC_DBG (1, "Not enough space to enqueue payload");
-      return 1;
+      return QUIC_ERROR_FULL_FIFO;
     }
   return 0;
 }
@@ -209,6 +256,7 @@ quic_send_packets (quic_ctx_t * ctx)
   quicly_context_t *quicly_context;
   app_worker_t *app_wrk;
   application_t *app;
+  int err;
 
   /* We have sctx, get qctx */
   if (ctx->c_quic_ctx_id.is_stream)
@@ -246,12 +294,12 @@ quic_send_packets (quic_ctx_t * ctx)
       if (max_packets < 2)
        break;
       num_packets = max_packets;
-      if (quicly_send (conn, packets, &num_packets))
+      if ((err = quicly_send (conn, packets, &num_packets)))
        goto quicly_error;
 
       for (i = 0; i != num_packets; ++i)
        {
-         if (quic_send_datagram (udp_session, packets[i]))
+         if ((err = quic_send_datagram (udp_session, packets[i])))
            goto quicly_error;
 
          quicly_context->packet_allocator->
@@ -268,7 +316,8 @@ stop_sending:
   return 0;
 
 quicly_error:
-  QUIC_DBG (1, "Error sending packets closing connection");
+  if (err != QUICLY_ERROR_PACKET_IGNORED)
+    clib_warning ("Quic error '%s'.", quic_format_err (err));
   quic_connection_closed (ctx->c_c_index, ctx->c_thread_index);
   return 1;
 }
@@ -1324,10 +1373,49 @@ quic_listener_get (u32 listener_index)
   return &ctx->connection;
 }
 
+static u8 *
+format_quic_ctx (u8 * s, va_list * args)
+{
+  quic_ctx_t *ctx = va_arg (*args, quic_ctx_t *);
+  u32 verbose = va_arg (*args, u32);
+
+  if (!ctx)
+    return s;
+  s = format (s, "[#%d][%s] ", ctx->c_thread_index, "Q");
+
+  if (ctx->is_listener)
+    {
+      s = format (s, "%s Listener: ", ctx->c_quic_ctx_id.is_stream ?
+                 "Stream" : "QSession");
+      if (verbose)
+       s = format (s, "app %d wrk %d", ctx->c_quic_ctx_id.parent_app_id,
+                   ctx->c_quic_ctx_id.parent_app_wrk_id);
+    }
+  else
+    {
+      if (ctx->c_is_ip4)
+       s = format (s, "%U:%d->%U:%d", format_ip4_address, &ctx->c_lcl_ip4,
+                   clib_net_to_host_u16 (ctx->c_lcl_port),
+                   format_ip4_address, &ctx->c_rmt_ip4,
+                   clib_net_to_host_u16 (ctx->c_rmt_port));
+      else
+       s = format (s, "%U:%d->%U:%d", format_ip6_address, &ctx->c_lcl_ip6,
+                   clib_net_to_host_u16 (ctx->c_lcl_port),
+                   format_ip6_address, &ctx->c_rmt_ip6,
+                   clib_net_to_host_u16 (ctx->c_rmt_port));
+    }
+  return s;
+}
+
 static u8 *
 format_quic_connection (u8 * s, va_list * args)
 {
-  s = format (s, "[QUIC] connection"); /* TODO */
+  u32 qc_index = va_arg (*args, u32);
+  u32 thread_index = va_arg (*args, u32);
+  u32 verbose = va_arg (*args, u32);
+  quic_ctx_t *ctx = quic_ctx_get (qc_index, thread_index);
+  if (ctx)
+    s = format (s, "%-50U", format_quic_ctx, ctx, verbose);
   return s;
 }
 
@@ -1344,7 +1432,14 @@ format_quic_half_open (u8 * s, va_list * args)
 static u8 *
 format_quic_listener (u8 * s, va_list * args)
 {
-  s = format (s, "[QUIC] listener");   /*  TODO */
+  u32 tci = va_arg (*args, u32);
+  u32 verbose = va_arg (*args, u32);
+  quic_ctx_t *ctx = quic_ctx_get (tci, vlib_get_thread_index ());
+  if (ctx)
+    {
+      ASSERT (ctx->is_listener);
+      s = format (s, "%-50U", format_quic_ctx, ctx, verbose);
+    }
   return s;
 }