tls: use fifo segments instead of chunks 87/30487/10
authorFlorin Coras <fcoras@cisco.com>
Fri, 18 Dec 2020 17:19:18 +0000 (09:19 -0800)
committerDave Barach <openvpp@barachs.net>
Sun, 20 Dec 2020 20:04:17 +0000 (20:04 +0000)
Type: refactor

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

src/plugins/tlsopenssl/tls_openssl.c
src/svm/svm_fifo.c
src/svm/svm_fifo.h

index 5e49dbf..789c64d 100644 (file)
@@ -113,32 +113,27 @@ openssl_lctx_get (u32 lctx_index)
 static int
 openssl_read_from_ssl_into_fifo (svm_fifo_t * f, SSL * ssl)
 {
-  u32 enq_now, enq_max;
-  svm_fifo_chunk_t *c;
-  int read, rv;
-
-  enq_max = svm_fifo_max_enqueue_prod (f);
-  if (!enq_max)
+  int read, rv, n_fs, i;
+  const int n_segs = 2;
+  svm_fifo_seg_t fs[n_segs];
+  u32 max_enq;
+
+  max_enq = svm_fifo_max_enqueue_prod (f);
+  n_fs = svm_fifo_provision_chunks (f, fs, n_segs, max_enq);
+  if (n_fs < 0)
     return 0;
 
-  svm_fifo_fill_chunk_list (f);
-
-  enq_now = clib_min (svm_fifo_max_write_chunk (f), enq_max);
-  if (!enq_now)
-    return 0;
-
-  read = SSL_read (ssl, svm_fifo_tail (f), enq_now);
+  /* Return early if we can't read anything */
+  read = SSL_read (ssl, fs[0].data, fs[0].len);
   if (read <= 0)
     return 0;
 
-  c = svm_fifo_tail_chunk (f);
-  while ((c = c->next) && read < enq_max)
+  for (i = 1; i < n_fs; i++)
     {
-      enq_now = clib_min (c->length, enq_max - read);
-      rv = SSL_read (ssl, c->data, enq_now);
+      rv = SSL_read (ssl, fs[i].data, fs[i].len);
       read += rv > 0 ? rv : 0;
 
-      if (rv < enq_now)
+      if (rv < fs[i].len)
        break;
     }
 
@@ -148,29 +143,27 @@ openssl_read_from_ssl_into_fifo (svm_fifo_t * f, SSL * ssl)
 }
 
 static int
-openssl_write_from_fifo_into_ssl (svm_fifo_t * f, SSL * ssl, u32 len)
+openssl_write_from_fifo_into_ssl (svm_fifo_t *f, SSL *ssl, u32 max_len)
 {
-  svm_fifo_chunk_t *c;
-  int wrote = 0, rv;
-  u32 deq_now;
+  int wrote = 0, rv, i = 0, len;
+  const int n_segs = 2;
+  svm_fifo_seg_t fs[n_segs];
 
-  deq_now = clib_min (svm_fifo_max_read_chunk (f), len);
-  wrote = SSL_write (ssl, svm_fifo_head (f), deq_now);
-  if (wrote <= 0)
+  len = svm_fifo_segments (f, 0, fs, n_segs, max_len);
+  if (len <= 0)
     return 0;
 
-  c = svm_fifo_head_chunk (f);
-  while ((c = c->next) && wrote < len)
+  while (wrote < len && i < n_segs)
     {
-      deq_now = clib_min (c->length, len - wrote);
-      rv = SSL_write (ssl, c->data, deq_now);
-      wrote += rv > 0 ? rv : 0;
-
-      if (rv < deq_now)
+      rv = SSL_write (ssl, fs[i].data, fs[i].len);
+      wrote += (rv > 0) ? rv : 0;
+      if (rv < fs[i].len)
        break;
+      i++;
     }
 
-  svm_fifo_dequeue_drop (f, wrote);
+  if (wrote)
+    svm_fifo_dequeue_drop (f, wrote);
 
   return wrote;
 }
index f1ac8d4..ff941a7 100644 (file)
@@ -1221,6 +1221,42 @@ svm_fifo_fill_chunk_list (svm_fifo_t * f)
   return 0;
 }
 
+int
+svm_fifo_provision_chunks (svm_fifo_t *f, svm_fifo_seg_t *fs, u32 n_segs,
+                          u32 len)
+{
+  u32 head, tail, n_avail, head_pos, n_bytes, fs_index = 1, clen;
+  svm_fifo_chunk_t *c;
+
+  f_load_head_tail_prod (f, &head, &tail);
+
+  if (f_free_count (f, head, tail) < len)
+    return SVM_FIFO_EFULL;
+
+  n_avail = f_chunk_end (f->end_chunk) - tail;
+
+  if (n_avail < len && f_try_chunk_alloc (f, head, tail, len))
+    return SVM_FIFO_EGROW;
+
+  c = f->tail_chunk;
+  head_pos = (tail - c->start_byte);
+  fs[0].data = c->data + head_pos;
+  fs[0].len = clib_min (c->length - head_pos, len);
+  n_bytes = fs[0].len;
+
+  while (n_bytes < len && fs_index < n_segs)
+    {
+      c = c->next;
+      clen = clib_min (c->length, len - n_bytes);
+      fs[fs_index].data = c->data;
+      fs[fs_index].len = clen;
+      n_bytes += clen;
+      fs_index += 1;
+    }
+
+  return fs_index;
+}
+
 int
 svm_fifo_segments (svm_fifo_t * f, u32 offset, svm_fifo_seg_t * fs,
                   u32 n_segs, u32 max_bytes)
index 4239e9d..2a05452 100644 (file)
@@ -207,6 +207,21 @@ svm_fifo_chunk_t *svm_fifo_chunk_alloc (u32 size);
  * @param f    fifo
  */
 int svm_fifo_fill_chunk_list (svm_fifo_t * f);
+/**
+ * Provision and return chunks for number of bytes requested
+ *
+ * Allocates enough chunks to cover the bytes requested and returns them
+ * in the fifo segment array. The number of bytes provisioned may be less
+ * than requested if not enough segments were provided.
+ *
+ * @param f            fifo
+ * @param fs           array of fifo segments
+ * @param n_segs       length of fifo segments array
+ * @param len          number of bytes to preallocate
+ * @return             number of fifo segments provisioned or error
+ */
+int svm_fifo_provision_chunks (svm_fifo_t *f, svm_fifo_seg_t *fs, u32 n_segs,
+                              u32 len);
 /**
  * Initialize rbtrees used for ooo lookups
  *