Esempio n. 1
0
static clib_error_t *
cj_config (vlib_main_t * vm, unformat_input_t * input)
{
  cj_main_t * cjm = &cj_main;
  int matched = 0;
  int enable = 0;

  while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (input, "records %d", &cjm->num_records))
        matched = 1;
      else if (unformat (input, "on"))
        enable = 1;
      else
        return clib_error_return (0, "cj_config: unknown input '%U'",
                                  format_unformat_error, input);
    }

  if (matched == 0)
    return 0;

  cjm->num_records = max_pow2 (cjm->num_records);
  vec_validate (cjm->records, cjm->num_records-1);
  memset (cjm->records, 0xff, cjm->num_records * sizeof (cj_record_t));
  cjm->tail = ~0;
  cjm->enable = enable;

  return 0;
}
Esempio n. 2
0
File: fifo.c Progetto: chrisy/vpp
void *
_clib_fifo_resize (void *v_old, uword n_new_elts, uword elt_bytes)
{
  void *v_new, *end, *head;
  uword n_old_elts, header_bytes;
  uword n_copy_bytes, n_zero_bytes;
  clib_fifo_header_t *f_new, *f_old;

  n_old_elts = clib_fifo_elts (v_old);
  n_new_elts += n_old_elts;
  if (n_new_elts < 32)
    n_new_elts = 32;
  else
    n_new_elts = max_pow2 (n_new_elts);

  header_bytes = vec_header_bytes (sizeof (clib_fifo_header_t));

  v_new = clib_mem_alloc_no_fail (n_new_elts * elt_bytes + header_bytes);
  v_new += header_bytes;

  f_new = clib_fifo_header (v_new);
  f_new->head_index = 0;
  f_new->tail_index = n_old_elts;
  _vec_len (v_new) = n_new_elts;

  /* Copy old -> new. */
  n_copy_bytes = n_old_elts * elt_bytes;
  if (n_copy_bytes > 0)
    {
      f_old = clib_fifo_header (v_old);
      end = v_old + _vec_len (v_old) * elt_bytes;
      head = v_old + f_old->head_index * elt_bytes;

      if (head + n_copy_bytes >= end)
	{
	  uword n = end - head;
	  clib_memcpy_fast (v_new, head, n);
	  clib_memcpy_fast (v_new + n, v_old, n_copy_bytes - n);
	}
      else
	clib_memcpy_fast (v_new, head, n_copy_bytes);
    }

  /* Zero empty space. */
  n_zero_bytes = (n_new_elts - n_old_elts) * elt_bytes;
  clib_memset (v_new + n_copy_bytes, 0, n_zero_bytes);

  clib_fifo_free (v_old);

  return v_new;
}
Esempio n. 3
0
int
test_mheap_main (unformat_input_t * input)
{
  int i, j, k, n_iterations;
  void *h, *h_mem;
  uword *objects = 0;
  u32 objects_used, really_verbose, n_objects, max_object_size;
  u32 check_mask, seed, trace, use_vm;
  u32 print_every = 0;
  u32 *data;
  mheap_t *mh;

  /* Validation flags. */
  check_mask = 0;
#define CHECK_VALIDITY 1
#define CHECK_DATA     2
#define CHECK_ALIGN    4
#define TEST1	       8

  n_iterations = 10;
  seed = 0;
  max_object_size = 100;
  n_objects = 1000;
  trace = 0;
  really_verbose = 0;
  use_vm = 0;

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      if (0 == unformat (input, "iter %d", &n_iterations)
	  && 0 == unformat (input, "count %d", &n_objects)
	  && 0 == unformat (input, "size %d", &max_object_size)
	  && 0 == unformat (input, "seed %d", &seed)
	  && 0 == unformat (input, "print %d", &print_every)
	  && 0 == unformat (input, "validdata %|",
			    &check_mask, CHECK_DATA | CHECK_VALIDITY)
	  && 0 == unformat (input, "valid %|",
			    &check_mask, CHECK_VALIDITY)
	  && 0 == unformat (input, "verbose %=", &really_verbose, 1)
	  && 0 == unformat (input, "trace %=", &trace, 1)
	  && 0 == unformat (input, "vm %=", &use_vm, 1)
	  && 0 == unformat (input, "align %|", &check_mask, CHECK_ALIGN)
	  && 0 == unformat (input, "test1 %|", &check_mask, TEST1))
	{
	  clib_warning ("unknown input `%U'", format_unformat_error, input);
	  return 1;
	}
    }

  /* Zero seed means use default. */
  if (!seed)
    seed = random_default_seed ();

  if (check_mask & TEST1)
    {
      return test1 ();
    }

  if_verbose
    ("testing %d iterations, %d %saligned objects, max. size %d, seed %d",
     n_iterations, n_objects, (check_mask & CHECK_ALIGN) ? "randomly " : "un",
     max_object_size, seed);

  vec_resize (objects, n_objects);
  if (vec_bytes (objects) > 0)	/* stupid warning be gone */
    clib_memset (objects, ~0, vec_bytes (objects));
  objects_used = 0;

  /* Allocate initial heap. */
  {
    uword size =
      max_pow2 (2 * n_objects * max_object_size * sizeof (data[0]));

    h_mem = clib_mem_alloc (size);
    if (!h_mem)
      return 0;

    h = mheap_alloc (h_mem, size);
  }

  if (trace)
    mheap_trace (h, trace);

  mh = mheap_header (h);

  if (use_vm)
    mh->flags &= ~MHEAP_FLAG_DISABLE_VM;
  else
    mh->flags |= MHEAP_FLAG_DISABLE_VM;

  if (check_mask & CHECK_VALIDITY)
    mh->flags |= MHEAP_FLAG_VALIDATE;

  for (i = 0; i < n_iterations; i++)
    {
      while (1)
	{
	  j = random_u32 (&seed) % vec_len (objects);
	  if (objects[j] != ~0 || i + objects_used < n_iterations)
	    break;
	}

      if (objects[j] != ~0)
	{
	  mheap_put (h, objects[j]);
	  objects_used--;
	  objects[j] = ~0;
	}
      else
	{
	  uword size, align, align_offset;

	  size = (random_u32 (&seed) % max_object_size) * sizeof (data[0]);
	  align = align_offset = 0;
	  if (check_mask & CHECK_ALIGN)
	    {
	      align = 1 << (random_u32 (&seed) % 10);
	      align_offset = round_pow2 (random_u32 (&seed) & (align - 1),
					 sizeof (u32));
	    }

	  h = mheap_get_aligned (h, size, align, align_offset, &objects[j]);

	  if (align > 0)
	    ASSERT (0 == ((objects[j] + align_offset) & (align - 1)));

	  ASSERT (objects[j] != ~0);
	  objects_used++;

	  /* Set newly allocated object with test data. */
	  if (check_mask & CHECK_DATA)
	    {
	      uword len;

	      data = (void *) h + objects[j];
	      len = mheap_len (h, data);

	      ASSERT (size <= mheap_data_bytes (h, objects[j]));

	      data[0] = len;
	      for (k = 1; k < len; k++)
		data[k] = objects[j] + k;
	    }
	}

      /* Verify that all used objects have correct test data. */
      if (check_mask & 2)
	{
	  for (j = 0; j < vec_len (objects); j++)
	    if (objects[j] != ~0)
	      {
		u32 *data = h + objects[j];
		uword len = data[0];
		for (k = 1; k < len; k++)
		  ASSERT (data[k] == objects[j] + k);
	      }
	}
      if (print_every != 0 && i > 0 && (i % print_every) == 0)
	fformat (stderr, "iteration %d: %U\n", i, format_mheap, h,
		 really_verbose);
    }

  if (verbose)
    fformat (stderr, "%U\n", format_mheap, h, really_verbose);
  mheap_free (h);
  clib_mem_free (h_mem);
  vec_free (objects);

  return 0;
}
Esempio n. 4
0
/* Given next hop vector is over-written with normalized one with sorted weights and
   with weights corresponding to the number of adjacencies for each next hop.
   Returns number of adjacencies in block. */
static u32 ip_multipath_normalize_next_hops (ip_lookup_main_t * lm,
					     ip_multipath_next_hop_t * raw_next_hops,
					     ip_multipath_next_hop_t ** normalized_next_hops)
{
  ip_multipath_next_hop_t * nhs;
  uword n_nhs, n_adj, n_adj_left, i;
  f64 sum_weight, norm, error;

  n_nhs = vec_len (raw_next_hops);
  ASSERT (n_nhs > 0);
  if (n_nhs == 0)
    return 0;

  /* Allocate enough space for 2 copies; we'll use second copy to save original weights. */
  nhs = *normalized_next_hops;
  vec_validate (nhs, 2*n_nhs - 1);

  /* Fast path: 1 next hop in block. */
  n_adj = n_nhs;
  if (n_nhs == 1)
    {
      nhs[0] = raw_next_hops[0];
      nhs[0].weight = 1;
      _vec_len (nhs) = 1;
      goto done;
    }

  else if (n_nhs == 2)
    {
      int cmp = next_hop_sort_by_weight (&raw_next_hops[0], &raw_next_hops[1]) < 0;

      /* Fast sort. */
      nhs[0] = raw_next_hops[cmp];
      nhs[1] = raw_next_hops[cmp ^ 1];

      /* Fast path: equal cost multipath with 2 next hops. */
      if (nhs[0].weight == nhs[1].weight)
	{
	  nhs[0].weight = nhs[1].weight = 1;
	  _vec_len (nhs) = 2;
	  goto done;
	}
    }
  else
    {
      memcpy (nhs, raw_next_hops, n_nhs * sizeof (raw_next_hops[0]));
      qsort (nhs, n_nhs, sizeof (nhs[0]), (void *) next_hop_sort_by_weight);
    }

  /* Find total weight to normalize weights. */
  sum_weight = 0;
  for (i = 0; i < n_nhs; i++)
    sum_weight += nhs[i].weight;

  /* In the unlikely case that all weights are given as 0, set them all to 1. */
  if (sum_weight == 0)
    {
      for (i = 0; i < n_nhs; i++)
	nhs[i].weight = 1;
      sum_weight = n_nhs;
    }

  /* Save copies of all next hop weights to avoid being overwritten in loop below. */
  for (i = 0; i < n_nhs; i++)
    nhs[n_nhs + i].weight = nhs[i].weight;

  /* Try larger and larger power of 2 sized adjacency blocks until we
     find one where traffic flows to within 1% of specified weights. */
  for (n_adj = max_pow2 (n_nhs); ; n_adj *= 2)
    {
      error = 0;

      norm = n_adj / sum_weight;
      n_adj_left = n_adj;
      for (i = 0; i < n_nhs; i++)
	{
	  f64 nf = nhs[n_nhs + i].weight * norm; /* use saved weights */
	  word n = flt_round_nearest (nf);

	  n = n > n_adj_left ? n_adj_left : n;
	  n_adj_left -= n;
	  error += fabs (nf - n);
	  nhs[i].weight = n;
	}
	
      nhs[0].weight += n_adj_left;

      /* Less than 5% average error per adjacency with this size adjacency block? */
      if (error <= lm->multipath_next_hop_error_tolerance*n_adj)
	{
	  /* Truncate any next hops with zero weight. */
	  _vec_len (nhs) = i;
	  break;
	}
    }

 done:
  /* Save vector for next call. */
  *normalized_next_hops = nhs;
  return n_adj;
}