aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDave Barach <dave@barachs.net>2019-11-08 08:22:28 -0500
committerAndrew Yourtchenko <ayourtch@gmail.com>2019-11-18 13:37:23 +0000
commit4fc160d7dd92acae430b15e0edabee6227d56e6e (patch)
tree561b4743d1f03258e6e404695d239e6b622271ed /src
parent636a8407586ed45a5b575ea58f4ad584e4a8a27c (diff)
vlib: fix handoff queue sequencing bug
Set vm->check_frame_queues after actually enqueuing a frame. Under obscure circumstances, the code managed to set check_frame_queues so far in advance that 100 dispatch cycles could elapse before the frame enqueue succeeded. That resulted in permanent lack of queue service. Type: fix Ticket: VPP-1734 Fixes: 18191 Signed-off-by: Dave Barach <dave@barachs.net> Change-Id: If2d398202b4ba2b96581d25e8142daef3f74c9e5 (cherry picked from commit 320998a8126766c0db92d9c7652f765f9565a7b5)
Diffstat (limited to 'src')
-rw-r--r--src/vlib/buffer_node.h3
1 files changed, 2 insertions, 1 deletions
diff --git a/src/vlib/buffer_node.h b/src/vlib/buffer_node.h
index 5ded5066563..96b50ae3551 100644
--- a/src/vlib/buffer_node.h
+++ b/src/vlib/buffer_node.h
@@ -517,7 +517,6 @@ vlib_buffer_enqueue_to_thread (vlib_main_t * vm, u32 frame_queue_index,
n_drop++;
goto next;
}
- vlib_mains[next_thread_index]->check_frame_queues = 1;
if (hf)
hf->n_vectors = VLIB_FRAME_SIZE - n_left_to_next_thread;
@@ -539,6 +538,7 @@ vlib_buffer_enqueue_to_thread (vlib_main_t * vm, u32 frame_queue_index,
{
hf->n_vectors = VLIB_FRAME_SIZE;
vlib_put_frame_queue_elt (hf);
+ vlib_mains[current_thread_index]->check_frame_queues = 1;
current_thread_index = ~0;
ptd->handoff_queue_elt_by_thread_index[next_thread_index] = 0;
hf = 0;
@@ -567,6 +567,7 @@ vlib_buffer_enqueue_to_thread (vlib_main_t * vm, u32 frame_queue_index,
if (1 || hf->n_vectors == hf->last_n_vectors)
{
vlib_put_frame_queue_elt (hf);
+ vlib_mains[i]->check_frame_queues = 1;
ptd->handoff_queue_elt_by_thread_index[i] = 0;
}
else
/a> 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
/*
 * Copyright (c) 2017-2019 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <vnet/session/session_table.h>
#include <vnet/session/session.h>

/**
 * Pool of session tables
 */
static session_table_t *lookup_tables;

session_table_t *
_get_session_tables (void)
{
  return lookup_tables;
}

session_table_t *
session_table_alloc (void)
{
  session_table_t *slt;
  pool_get_aligned (lookup_tables, slt, CLIB_CACHE_LINE_BYTES);
  clib_memset (slt, 0, sizeof (*slt));
  return slt;
}

u32
session_table_index (session_table_t * slt)
{
  return (slt - lookup_tables);
}

session_table_t *
session_table_get (u32 table_index)
{
  if (pool_is_free_index (lookup_tables, table_index))
    return 0;
  return pool_elt_at_index (lookup_tables, table_index);
}

#define foreach_hash_table_parameter            \
  _(v4,session,buckets,20000)                   \
  _(v4,session,memory,(64<<20))                 \
  _(v6,session,buckets,20000)                   \
  _(v6,session,memory,(64<<20))                 \
  _(v4,halfopen,buckets,20000)                  \
  _(v4,halfopen,memory,(64<<20))                \
  _(v6,halfopen,buckets,20000)                  \
  _(v6,halfopen,memory,(64<<20))

void
session_table_free (session_table_t *slt, u8 fib_proto)
{
  u8 all = fib_proto > FIB_PROTOCOL_IP6 ? 1 : 0;
  int i;

  for (i = 0; i < TRANSPORT_N_PROTOS; i++)
    session_rules_table_free (&slt->session_rules[i]);

  vec_free (slt->session_rules);

  if (fib_proto == FIB_PROTOCOL_IP4 || all)
    {
      clib_bihash_free_16_8 (&slt->v4_session_hash);
      clib_bihash_free_16_8 (&slt->v4_half_open_hash);
    }
  if (fib_proto == FIB_PROTOCOL_IP6 || all)
    {
      clib_bihash_free_48_8 (&slt->v6_session_hash);
      clib_bihash_free_48_8 (&slt->v6_half_open_hash);
    }

  pool_put (lookup_tables, slt);
}

/**
 * Initialize session table hash tables
 *
 * If vpp configured with set of table parameters it uses them,
 * otherwise it uses defaults above.
 */
void
session_table_init (session_table_t * slt, u8 fib_proto)
{
  u8 all = fib_proto > FIB_PROTOCOL_IP6 ? 1 : 0;
  int i;

#define _(af,table,parm,value) 						\
  u32 configured_##af##_##table##_table_##parm = value;
  foreach_hash_table_parameter;
#undef _

#define _(af,table,parm,value)                                          \
  if (session_main.configured_##af##_##table##_table_##parm)    \
    configured_##af##_##table##_table_##parm =                          \
      session_main.configured_##af##_##table##_table_##parm;
  foreach_hash_table_parameter;
#undef _

  if (fib_proto == FIB_PROTOCOL_IP4 || all)
    {
      clib_bihash_init2_args_16_8_t _a, *a = &_a;

      memset (a, 0, sizeof (*a));
      a->h = &slt->v4_session_hash;
      a->name = "v4 session table";
      a->nbuckets = configured_v4_session_table_buckets;
      a->memory_size = configured_v4_session_table_memory;
      a->dont_add_to_all_bihash_list = 1;
      a->instantiate_immediately = 1;
      clib_bihash_init2_16_8 (a);

      memset (a, 0, sizeof (*a));
      a->h = &slt->v4_half_open_hash;
      a->name = "v4 half-open table";
      a->nbuckets = configured_v4_halfopen_table_buckets;
      a->memory_size = configured_v4_halfopen_table_memory;
      a->dont_add_to_all_bihash_list = 1;
      a->instantiate_immediately = 1;
      clib_bihash_init2_16_8 (a);
    }
  if (fib_proto == FIB_PROTOCOL_IP6 || all)
    {
      clib_bihash_init2_args_48_8_t _a, *a = &_a;

      memset (a, 0, sizeof (*a));
      a->h = &slt->v6_session_hash;
      a->name = "v6 session table";
      a->nbuckets = configured_v6_session_table_buckets;
      a->memory_size = configured_v6_session_table_memory;
      a->dont_add_to_all_bihash_list = 1;
      a->instantiate_immediately = 1;
      clib_bihash_init2_48_8 (a);

      memset (a, 0, sizeof (*a));
      a->h = &slt->v6_half_open_hash;
      a->name = "v6 half-open table";
      a->nbuckets = configured_v6_halfopen_table_buckets;
      a->memory_size = configured_v6_halfopen_table_memory;
      a->dont_add_to_all_bihash_list = 1;
      a->instantiate_immediately = 1;
      clib_bihash_init2_48_8 (a);
    }

  vec_validate (slt->session_rules, TRANSPORT_N_PROTOS - 1);
  for (i = 0; i < TRANSPORT_N_PROTOS; i++)
    session_rules_table_init (&slt->session_rules[i]);
}

typedef struct _ip4_session_table_walk_ctx_t
{
  ip4_session_table_walk_fn_t fn;
  void *ctx;
} ip4_session_table_walk_ctx_t;

static int
ip4_session_table_walk_cb (clib_bihash_kv_16_8_t * kvp, void *arg)
{
  ip4_session_table_walk_ctx_t *ctx = arg;
  ctx->fn (kvp, ctx->ctx);
  return (BIHASH_WALK_CONTINUE);
}

void
ip4_session_table_walk (clib_bihash_16_8_t * hash,
			ip4_session_table_walk_fn_t fn, void *arg)
{
  ip4_session_table_walk_ctx_t ctx = {
    .fn = fn,
    .ctx = arg,
  };
  clib_bihash_foreach_key_value_pair_16_8 (hash, ip4_session_table_walk_cb,
					   &ctx);
}

u32
session_table_memory_size (session_table_t *st)
{
  u64 total_size = 0;

  if (clib_bihash_is_initialised_16_8 (&st->v4_session_hash))
    {
      clib_bihash_alloc_chunk_16_8_t *c = st->v4_session_hash.chunks;
      while (c)
	{
	  total_size += c->size;
	  c = c->next;
	}
      c = st->v4_half_open_hash.chunks;
      while (c)
	{
	  total_size += c->size;
	  c = c->next;
	}
    }

  if (clib_bihash_is_initialised_48_8 (&st->v6_session_hash))
    {
      clib_bihash_alloc_chunk_48_8_t *c = st->v6_session_hash.chunks;
      while (c)
	{
	  total_size += c->size;
	  c = c->next;
	}
      c = st->v6_half_open_hash.chunks;
      while (c)
	{
	  total_size += c->size;
	  c = c->next;
	}
    }

  return total_size;
}

u8 *
format_session_table (u8 *s, va_list *args)
{
  session_table_t *st = va_arg (*args, session_table_t *);

  if (clib_bihash_is_initialised_16_8 (&st->v4_session_hash))
    {
      s = format (s, "%U", format_bihash_16_8, &st->v4_session_hash, 0);
      s = format (s, "%U", format_bihash_16_8, &st->v4_half_open_hash, 0);
    }

  if (clib_bihash_is_initialised_48_8 (&st->v6_session_hash))
    {
      s = format (s, "%U", format_bihash_48_8, &st->v6_session_hash, 0);
      s = format (s, "%U", format_bihash_48_8, &st->v6_half_open_hash, 0);
    }

  return s;
}

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */