aboutsummaryrefslogtreecommitdiffstats
path: root/src/vppinfra/test_bihash_template.c
AgeCommit message (Expand)AuthorFilesLines
2018-08-22bihash: add support for reuse of expired entry when bucket is full (VPP-1272)Matus Fabian1-0/+45
2018-07-20Fine-grained add / delete lockingDave Barach1-36/+106
2018-02-22bihash table size perf/scale improvementsDave Barach1-7/+17
2018-02-08Minimize bihash memory consumptionDave Barach1-93/+145
2017-07-19Add a bihash prefetchable bucket-level cacheDave Barach1-6/+55
2017-05-18VPP-847: improve bihash template memory allocator performanceDave Barach1-1/+44
2017-01-02Handle execessive hash collisions, VPP-555Dave Barach1-26/+6
2016-12-28Reorganize source tree to use single autotools instanceDamjan Marion1-0/+297
8 189 190
/*
 * Copyright (c) 2020 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/vnet.h>
#include <vppinfra/linux/sysfs.h>
#include <perfmon/perfmon.h>
#include <perfmon/intel/core.h>
#include <perfmon/intel/uncore.h>

VLIB_REGISTER_LOG_CLASS (if_intel_uncore_log, static) = {
  .class_name = "perfmon",
  .subclass_name = "intel-uncore",
};

#define log_debug(fmt, ...)                                                   \
  vlib_log_debug (if_intel_uncore_log.class, fmt, __VA_ARGS__)
#define log_warn(fmt, ...)                                                    \
  vlib_log_warn (if_intel_uncore_log.class, fmt, __VA_ARGS__)
#define log_err(fmt, ...)                                                     \
  vlib_log_err (if_intel_uncore_log.class, fmt, __VA_ARGS__)

#define PERF_INTEL_CODE(event, umask, edge, any, inv, cmask)                  \
  ((event) | (umask) << 8 | (edge) << 18 | (any) << 21 | (inv) << 23 |        \
   (cmask) << 24)

static perfmon_event_t intel_uncore_events[] = {
#define _(unit, event, umask, n, suffix, desc)                                \
  [INTEL_UNCORE_E_##unit##_##n##_##suffix] = {                                \
    .config = (event) | (umask) << 8,                                         \
    .name = #n "." #suffix,                                                   \
    .description = desc,                                                      \
    .type_from_instance = 1,                                                  \
    .instance_type = INTEL_UNCORE_UNIT_##unit,                                \
  },

  foreach_intel_uncore_event
#undef _
};

static int
intel_uncore_instance_name_cmp (void *v1, void *v2)
{
  perfmon_instance_t *i1 = v1;
  perfmon_instance_t *i2 = v2;
  return strcmp (i1->name, i2->name);
}

static void
intel_uncore_add_unit (perfmon_source_t *src, intel_uncore_unit_type_t u,
		       char *name, char *type_str, char *fmt,
		       int *socket_by_cpu_id)
{
  static char *base_path = "/sys/bus/event_source/devices/uncore";
  clib_error_t *err;
  clib_bitmap_t *cpumask = 0;
  perfmon_instance_t *in;
  perfmon_instance_type_t *it;
  u8 *s = 0;
  int i = 0, j;
  u32 perf_type;

  vec_validate (src->instances_by_type, u);
  it = vec_elt_at_index (src->instances_by_type, u);
  it->name = type_str;

  while (1)
    {
      s = format (s, "%s_%s_%u/type%c", base_path, name, i, 0);
      if ((err = clib_sysfs_read ((char *) s, "%u", &perf_type)))
	break;
      vec_reset_length (s);

      s = format (s, "%s_%s_%u/cpumask%c", base_path, name, i, 0);
      if ((err = clib_sysfs_read ((char *) s, "%U", unformat_bitmap_list,
				  &cpumask)))
	break;
      vec_reset_length (s);

      clib_bitmap_foreach (j, cpumask)
	{
	  vec_add2 (it->instances, in, 1);
	  in->type = perf_type;
	  in->cpu = j;
	  in->pid = -1;
	  in->name = (char *) format (0, fmt, socket_by_cpu_id[j], i);
	  vec_terminate_c_string (in->name);
	  log_debug ("found %s %s", type_str, in->name);
	}
      i++;
    };
  clib_error_free (err);
  clib_bitmap_free (cpumask);
  vec_free (s);
}

static clib_error_t *
intel_uncore_init (vlib_main_t *vm, perfmon_source_t *src)
{
  clib_error_t *err = 0;
  clib_bitmap_t *node_bitmap = 0, *cpumask = 0;
  int *numa_by_cpu_id = 0;
  u32 i, j;
  u8 *s = 0;

  if ((err = clib_sysfs_read ("/sys/devices/system/node/has_cpu", "%U",
			      unformat_bitmap_list, &node_bitmap)))
    {
      clib_error_free (err);
      return clib_error_return (0, "failed to discover numa topology");
    }

  clib_bitmap_foreach (i, node_bitmap)
    {
      s = format (s, "/sys/devices/system/node/node%u/cpulist%c", i, 0);
      if ((err = clib_sysfs_read ((char *) s, "%U", unformat_bitmap_list,
				  &cpumask)))
	{
	  clib_error_free (err);
	  err = clib_error_return (0, "failed to discover numa topology");
	  goto done;
	}

      if (!cpumask)
	{
	  clib_error_free (err);
	  err = clib_error_return (
	    0, "while discovering numa topology: cpumask unexpectedly NULL");
	  goto done;
	}

      clib_bitmap_foreach (j, cpumask)
	{
	  vec_validate_init_empty (numa_by_cpu_id, j, -1);
	  numa_by_cpu_id[j] = i;
	}
      clib_bitmap_free (cpumask);
      vec_reset_length (s);
    }

#define _(t, n, name, fmt)                                                    \
  intel_uncore_add_unit (src, INTEL_UNCORE_UNIT_##t, n, name, fmt,            \
			 numa_by_cpu_id);
  foreach_intel_uncore_unit_type;
#undef _

  for (i = 0, j = 0; i < vec_len (src->instances_by_type); i++)
    {
      perfmon_instance_type_t *it;

      it = vec_elt_at_index (src->instances_by_type, i);
      vec_sort_with_function (it->instances, intel_uncore_instance_name_cmp);
      j += vec_len (it->instances);
    }

  if (j == 0)
    {
      vec_free (src->instances_by_type);
      return clib_error_return (0, "no uncore units found");
    }

done:
  vec_free (s);
  vec_free (cpumask);
  vec_free (node_bitmap);
  vec_free (numa_by_cpu_id);
  return err;
}

format_function_t format_intel_core_config;

PERFMON_REGISTER_SOURCE (intel_uncore) = {
  .name = "intel-uncore",
  .description = "intel uncore events",
  .events = intel_uncore_events,
  .n_events = INTEL_UNCORE_N_EVENTS,
  .init_fn = intel_uncore_init,
  .format_config = format_intel_core_config,
};