ACL plugin support tagged subinterfaces
[vpp.git] / src / vlib / buffer_funcs.h
index 97442e1..7224e08 100644 (file)
@@ -106,12 +106,15 @@ uword vlib_buffer_length_in_chain_slow_path (vlib_main_t * vm,
 always_inline uword
 vlib_buffer_length_in_chain (vlib_main_t * vm, vlib_buffer_t * b)
 {
-  uword l = b->current_length + b->total_length_not_including_first_buffer;
-  if (PREDICT_FALSE ((b->flags & (VLIB_BUFFER_NEXT_PRESENT
-                                 | VLIB_BUFFER_TOTAL_LENGTH_VALID))
-                    == VLIB_BUFFER_NEXT_PRESENT))
-    return vlib_buffer_length_in_chain_slow_path (vm, b);
-  return l;
+  uword len = b->current_length;
+
+  if (PREDICT_TRUE ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0))
+    return len;
+
+  if (PREDICT_TRUE (b->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID))
+    return len + b->total_length_not_including_first_buffer;
+
+  return vlib_buffer_length_in_chain_slow_path (vm, b);
 }
 
 /** \brief Get length in bytes of the buffer index buffer chain
@@ -159,7 +162,10 @@ vlib_buffer_contents (vlib_main_t * vm, u32 buffer_index, u8 * contents)
 always_inline u64
 vlib_get_buffer_data_physical_address (vlib_main_t * vm, u32 buffer_index)
 {
-  return vlib_physmem_offset_to_physical (&vm->physmem_main,
+  vlib_physmem_region_index_t pri;
+  vlib_buffer_t *b = vlib_get_buffer (vm, buffer_index);
+  pri = vm->buffer_main->buffer_pools[b->buffer_pool_index].physmem_region;
+  return vlib_physmem_offset_to_physical (vm, pri,
                                          (((uword) buffer_index) <<
                                           CLIB_LOG2_CACHE_LINE_BYTES) +
                                          STRUCT_OFFSET_OF (vlib_buffer_t,
@@ -216,9 +222,10 @@ always_inline vlib_buffer_known_state_t
 vlib_buffer_is_known (vlib_main_t * vm, u32 buffer_index)
 {
   vlib_buffer_main_t *bm = vm->buffer_main;
-  ASSERT (vlib_get_thread_index () == 0);
 
+  clib_spinlock_lock (&bm->buffer_known_hash_lockp);
   uword *p = hash_get (bm->buffer_known_hash, buffer_index);
+  clib_spinlock_unlock (&bm->buffer_known_hash_lockp);
   return p ? p[0] : VLIB_BUFFER_UNKNOWN;
 }
 
@@ -228,8 +235,9 @@ vlib_buffer_set_known_state (vlib_main_t * vm,
                             vlib_buffer_known_state_t state)
 {
   vlib_buffer_main_t *bm = vm->buffer_main;
-  ASSERT (vlib_get_thread_index () == 0);
+  clib_spinlock_lock (&bm->buffer_known_hash_lockp);
   hash_set (bm->buffer_known_hash, buffer_index, state);
+  clib_spinlock_unlock (&bm->buffer_known_hash_lockp);
 }
 
 /* Validates sanity of a single buffer.
@@ -261,6 +269,24 @@ vlib_buffer_round_size (u32 size)
   return round_pow2 (size, sizeof (vlib_buffer_t));
 }
 
+always_inline u32
+vlib_buffer_get_free_list_index (vlib_buffer_t * b)
+{
+  return b->flags & VLIB_BUFFER_FREE_LIST_INDEX_MASK;
+}
+
+always_inline void
+vlib_buffer_set_free_list_index (vlib_buffer_t * b, u32 index)
+{
+  /* if there is an need for more free lists we should consider
+     storig data in the 2nd cacheline */
+  ASSERT (VLIB_BUFFER_FREE_LIST_INDEX_MASK & 1);
+  ASSERT (index <= VLIB_BUFFER_FREE_LIST_INDEX_MASK);
+
+  b->flags &= ~VLIB_BUFFER_FREE_LIST_INDEX_MASK;
+  b->flags |= index & VLIB_BUFFER_FREE_LIST_INDEX_MASK;
+}
+
 /** \brief Allocate buffers from specific freelist into supplied array
 
     @param vm - (vlib_main_t *) vlib main data structure pointer
@@ -381,7 +407,7 @@ vlib_buffer_get_buffer_free_list (vlib_main_t * vm, vlib_buffer_t * b,
   vlib_buffer_main_t *bm = vm->buffer_main;
   u32 i;
 
-  *index = i = b->free_list_index;
+  *index = i = vlib_buffer_get_free_list_index (b);
   return pool_elt_at_index (bm->buffer_free_list_pool, i);
 }
 
@@ -432,43 +458,6 @@ vlib_copy_buffers (u32 * dst, u32 * src, u32 n)
     }
 }
 
-always_inline void *
-vlib_physmem_alloc_aligned (vlib_main_t * vm, clib_error_t ** error,
-                           uword n_bytes, uword alignment)
-{
-  void *r =
-    vm->os_physmem_alloc_aligned (&vm->physmem_main, n_bytes, alignment);
-  if (!r)
-    *error =
-      clib_error_return (0, "failed to allocate %wd bytes of I/O memory",
-                        n_bytes);
-  else
-    *error = 0;
-  return r;
-}
-
-/* By default allocate I/O memory with cache line alignment. */
-always_inline void *
-vlib_physmem_alloc (vlib_main_t * vm, clib_error_t ** error, uword n_bytes)
-{
-  return vlib_physmem_alloc_aligned (vm, error, n_bytes,
-                                    CLIB_CACHE_LINE_BYTES);
-}
-
-always_inline void
-vlib_physmem_free (vlib_main_t * vm, void *mem)
-{
-  return vm->os_physmem_free (mem);
-}
-
-always_inline u64
-vlib_physmem_virtual_to_physical (vlib_main_t * vm, void *mem)
-{
-  vlib_physmem_main_t *pm = &vm->physmem_main;
-  uword o = pointer_to_uword (mem) - pm->virtual.start;
-  return vlib_physmem_offset_to_physical (pm, o);
-}
-
 /* Append given data to end of buffer, possibly allocating new buffers. */
 u32 vlib_buffer_add_data (vlib_main_t * vm,
                          u32 free_list_index,
@@ -569,7 +558,8 @@ vlib_buffer_clone (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
     }
 
   n_buffers = vlib_buffer_alloc_from_free_list (vm, buffers, n_buffers,
-                                               s->free_list_index);
+                                               vlib_buffer_get_free_list_index
+                                               (s));
   if (PREDICT_FALSE (n_buffers == 0))
     {
       buffers[0] = src_buffer;
@@ -581,7 +571,8 @@ vlib_buffer_clone (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
       vlib_buffer_t *d = vlib_get_buffer (vm, buffers[i]);
       d->current_data = s->current_data;
       d->current_length = head_end_offset;
-      d->free_list_index = s->free_list_index;
+      vlib_buffer_set_free_list_index (d,
+                                      vlib_buffer_get_free_list_index (s));
       d->total_length_not_including_first_buffer =
        s->total_length_not_including_first_buffer + s->current_length -
        head_end_offset;
@@ -615,7 +606,8 @@ vlib_buffer_attach_clone (vlib_main_t * vm, vlib_buffer_t * head,
                          vlib_buffer_t * tail)
 {
   ASSERT ((head->flags & VLIB_BUFFER_NEXT_PRESENT) == 0);
-  ASSERT (head->free_list_index == tail->free_list_index);
+  ASSERT (vlib_buffer_get_free_list_index (head) ==
+         vlib_buffer_get_free_list_index (tail));
 
   head->flags |= VLIB_BUFFER_NEXT_PRESENT;
   head->flags &= ~VLIB_BUFFER_TOTAL_LENGTH_VALID;
@@ -791,7 +783,7 @@ vlib_buffer_init_for_free_list (vlib_buffer_t * dst,
          CLIB_CACHE_LINE_BYTES * 2);
 
   /* Make sure buffer template is sane. */
-  ASSERT (fl->index == fl->buffer_init_template.free_list_index);
+  ASSERT (fl->index == vlib_buffer_get_free_list_index (src));
 
   clib_memcpy (STRUCT_MARK_PTR (dst, template_start),
               STRUCT_MARK_PTR (src, template_start),
@@ -806,9 +798,13 @@ vlib_buffer_init_for_free_list (vlib_buffer_t * dst,
   _(current_data);
   _(current_length);
   _(flags);
-  _(free_list_index);
 #undef _
-  ASSERT (dst->total_length_not_including_first_buffer == 0);
+  /* ASSERT (dst->total_length_not_including_first_buffer == 0); */
+  /* total_length_not_including_first_buffer is not in the template anymore
+   * so it may actually not zeroed for some buffers. One option is to
+   * uncomment the line lower (comes at a cost), the other, is to just  not
+   * care */
+  /* dst->total_length_not_including_first_buffer = 0; */
   ASSERT (dst->n_add_refs == 0);
 }
 
@@ -822,6 +818,18 @@ vlib_buffer_add_to_free_list (vlib_main_t * vm,
   if (PREDICT_TRUE (do_init))
     vlib_buffer_init_for_free_list (b, f);
   vec_add1_aligned (f->buffers, buffer_index, CLIB_CACHE_LINE_BYTES);
+
+  if (vec_len (f->buffers) > 4 * VLIB_FRAME_SIZE)
+    {
+      vlib_buffer_free_list_t *mf;
+      mf = vlib_buffer_get_free_list (vlib_mains[0], f->index);
+      clib_spinlock_lock (&mf->global_buffers_lock);
+      /* keep last stored buffers, as they are more likely hot in the cache */
+      vec_add_aligned (mf->global_buffers, f->buffers, VLIB_FRAME_SIZE,
+                      CLIB_CACHE_LINE_BYTES);
+      vec_delete (f->buffers, VLIB_FRAME_SIZE, 0);
+      clib_spinlock_unlock (&mf->global_buffers_lock);
+    }
 }
 
 always_inline void
@@ -832,7 +840,7 @@ vlib_buffer_init_two_for_free_list (vlib_buffer_t * dst0,
   vlib_buffer_t *src = &fl->buffer_init_template;
 
   /* Make sure buffer template is sane. */
-  ASSERT (fl->index == fl->buffer_init_template.free_list_index);
+  ASSERT (fl->index == vlib_buffer_get_free_list_index (src));
 
   clib_memcpy (STRUCT_MARK_PTR (dst0, template_start),
               STRUCT_MARK_PTR (src, template_start),
@@ -853,7 +861,6 @@ vlib_buffer_init_two_for_free_list (vlib_buffer_t * dst0,
   _(current_data);
   _(current_length);
   _(flags);
-  _(free_list_index);
 #undef _
 
   ASSERT (dst0->total_length_not_including_first_buffer == 0);