aboutsummaryrefslogtreecommitdiffstats
path: root/VIRL_TOPOLOGY_UBUNTU
AgeCommit message (Expand)AuthorFilesLines
2017-03-01Use common files to store distro related data for VIRLJan Gelety1-0/+1
n215'>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 255 256 257
/*
 * Copyright (c) 2015 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 <vppinfra/time.h>
#include <vppinfra/cache.h>
#include <vppinfra/error.h>

#include <vppinfra/heap.h>
#include <vppinfra/format.h>
#include <vppinfra/random.h>
#include <vppinfra/hash.h>

#include <vppinfra/flowhash_8_8.h>

/* Not actually tested here. But included for compilation purposes. */
#include <vppinfra/flowhash_24_16.h>

typedef struct
{
  u64 seed;
  u32 fixed_entries;
  u32 collision_buckets;
  u32 nitems;
  u32 iterations;
  u32 prefetch;
  int non_random_keys;
  uword *key_hash;
  flowhash_lkey_8_8_t *keys;
  flowhash_8_8_t *hash;
  clib_time_t clib_time;
  unformat_input_t *input;
} test_main_t;

test_main_t test_main;

static clib_error_t *
test_flowhash (test_main_t * tm)
{
  f64 before, delta;
  u64 total;
  u32 overflow;
  int i, j;
  uword *p;
  tm->hash = flowhash_alloc_8_8 (tm->fixed_entries, tm->collision_buckets);
  if (tm->hash == NULL)
    return clib_error_return (0, "Could not alloc hash");

  fformat (stdout, "Allocated hash memory size: %llu\n",
	   flowhash_memory_size (tm->hash));

  fformat (stdout, "Pick %lld unique %s keys...\n",
	   tm->nitems, tm->non_random_keys ? "non-random" : "random");

  for (i = 0; i < tm->nitems; i++)
    {
      flowhash_lkey_8_8_t rndkey;
      if (tm->non_random_keys == 0)
	{
	again:
	  rndkey.as_u64[0] = random_u64 (&tm->seed);
	  if ((p = hash_get (tm->key_hash, rndkey.as_u64[0])))
	    goto again;
	}
      else
	rndkey.as_u64[0] = (u64) (i + 1) << 16;

      hash_set (tm->key_hash, rndkey.as_u64[0], i + 1);
      vec_add1 (tm->keys, rndkey);
    }

  hash_free (tm->key_hash);

  /* Additions */
  overflow = 0;
  before = clib_time_now (&tm->clib_time);
  fformat (stdout, "Adding %u items...\n", tm->nitems);
  for (i = 0; i < tm->nitems; i++)
    {
      u32 hash = flowhash_hash_8_8 (&tm->keys[i]);
      u32 ei;
      flowhash_get_8_8 (tm->hash, &tm->keys[i], hash, 1, &ei);
      if (flowhash_is_overflow (ei))
	overflow++;

      /* Set value (No matter if success) */
      flowhash_value (tm->hash, ei)->as_u64[0] = i + 1;

      /* Save value until time > 1 */
      flowhash_timeout (tm->hash, ei) = 1;
    }

  delta = clib_time_now (&tm->clib_time) - before;
  total = tm->nitems;
  fformat (stdout, "%lld additions in %.6f seconds\n", total, delta);
  if (delta > 0)
    fformat (stdout, "%.f additions per second\n", ((f64) total) / delta);

  fformat (stdout, "%u elements in table\n", flowhash_elts_8_8 (tm->hash, 1));
  fformat (stdout, "Flowhash counters:\n");
  fformat (stdout, "  collision-lookup: %lu\n",
	   tm->hash->collision_lookup_counter);
  fformat (stdout, "  not-enough-buckets: %lu\n",
	   tm->hash->not_enough_buckets_counter);
  fformat (stdout, "  overflows: %lu\n", overflow);

  /* Lookups (very similar to additions) */
  overflow = 0;
  before = clib_time_now (&tm->clib_time);
  fformat (stdout, "Looking up %u items %u times...\n", tm->nitems,
	   tm->iterations);

  for (j = 0; j < tm->iterations; j++)
    {
      i = 0;
      if (tm->prefetch)
	for (; i < tm->nitems - tm->prefetch; i++)
	  {
	    u32 ei;
	    u32 hash = flowhash_hash_8_8 (&tm->keys[i + tm->prefetch]);
	    flowhash_prefetch (tm->hash, hash);
	    hash = flowhash_hash_8_8 (&tm->keys[i]);
	    flowhash_get_8_8 (tm->hash, &tm->keys[i], hash, 1, &ei);
	    if (flowhash_is_overflow (ei))
	      overflow++;
	    else if (flowhash_timeout (tm->hash, ei) != 1)
	      clib_warning ("Key not found: %lld\n", tm->keys[i].as_u64[0]);
	    else if (flowhash_value (tm->hash, ei)->as_u64[0] != i + 1)
	      clib_warning ("Value mismatch for key %lld\n",
			    tm->keys[i].as_u64[0]);
	  }

      for (; i < tm->nitems; i++)
	{
	  u32 ei;
	  u32 hash = flowhash_hash_8_8 (&tm->keys[i]);
	  flowhash_get_8_8 (tm->hash, &tm->keys[i], hash, 1, &ei);
	  if (flowhash_is_overflow (ei))
	    overflow++;
	  else if (flowhash_timeout (tm->hash, ei) != 1)
	    clib_warning ("Key not found: %lld\n", tm->keys[i].as_u64[0]);
	  else if (flowhash_value (tm->hash, ei)->as_u64[0] != i + 1)
	    clib_warning ("Value mismatch for key %lld\n",
			  tm->keys[i].as_u64[0]);
	}
    }

  delta = clib_time_now (&tm->clib_time) - before;
  total = tm->nitems * tm->iterations;
  fformat (stdout, "%lld lookups in %.6f seconds\n", total, delta);
  if (delta > 0)
    fformat (stdout, "%.f lookups per second\n", ((f64) total) / delta);

  /* Delete */
  for (i = 0; i < tm->nitems; i++)
    {
      u32 hash = flowhash_hash_8_8 (&tm->keys[i]);
      u32 ei;
      flowhash_get_8_8 (tm->hash, &tm->keys[i], hash, 1, &ei);
      flowhash_timeout (tm->hash, ei) = 0;
    }

  fformat (stdout, "%u elements in table\n", flowhash_elts_8_8 (tm->hash, 1));

  vec_free (tm->keys);
  flowhash_free_8_8 (tm->hash);

  return NULL;
}

clib_error_t *
test_flowhash_main (test_main_t * tm)
{
  unformat_input_t *i = tm->input;
  clib_error_t *error;

  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "seed %u", &tm->seed))
	;
      else if (unformat (i, "fixed-entries %d", &tm->fixed_entries))
	;
      else if (unformat (i, "collision-buckets %d", &tm->collision_buckets))
	;
      else if (unformat (i, "non-random-keys"))
	tm->non_random_keys = 1;
      else if (unformat (i, "nitems %d", &tm->nitems))
	;
      else if (unformat (i, "prefetch %d", &tm->prefetch))
	;
      else if (unformat (i, "iterations %d", &tm->iterations))
	;
      else
	return clib_error_return (0, "unknown input '%U'",
				  format_unformat_error, i);
    }

  error = test_flowhash (tm);
  return error;
}

#ifdef CLIB_UNIX
int
main (int argc, char *argv[])
{

  unformat_input_t i;
  clib_error_t *error;
  test_main_t *tm = &test_main;

  clib_mem_init (0, 3ULL << 30);

  tm->fixed_entries = 8 << 20;
  tm->collision_buckets = 1 << 20;
  tm->seed = 0xdeadf00l;
  tm->iterations = 1;
  tm->input = &i;
  tm->nitems = 1000;
  tm->non_random_keys = 0;
  tm->key_hash = hash_create (0, sizeof (uword));
  tm->prefetch = 0;
  clib_time_init (&tm->clib_time);

  unformat_init_command_line (&i, argv);
  error = test_flowhash_main (tm);
  unformat_free (&i);

  if (error)
    {
      clib_error_report (error);
      return 1;
    }
  return 0;

  return 0;
}
#endif /* CLIB_UNIX */


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