aboutsummaryrefslogtreecommitdiffstats
path: root/extras/vpp_config
ModeNameSize
-rw-r--r--LICENSE.txt11358logstatsplain
-rw-r--r--README.rst18719logstatsplain
-rw-r--r--__init__.py0logstatsplain
d---------data332logstatsplain
d---------scripts161logstatsplain
-rw-r--r--setup.cfg253logstatsplain
-rw-r--r--setup.py1421logstatsplain
-rwxr-xr-xvpp_config.py22106logstatsplain
d---------vpplib366logstatsplain
#dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
/*
 * SPDX-License-Identifier: Apache-2.0
 * Copyright(c) 2021 Cisco Systems, Inc.
 */

/* Virtual time allows to adjust VPP clock by arbitrary amount of time.
 * It is done such that the order of timer expirations is maintained,
 * and if a timer expiration callback reschedule another timer, this
 * timer will also properly expire in the right order. IOW, the order
 * of events is preserved.
 *
 * When moving time forward, each VPP thread (main and workers) runs an
 * instance of the input node 'virtual-time-input' below. This node is
 * responsible of advancing its own VPP thread clock to the next timer
 * expiration.  IOW each thread will move its clock independently one
 * timer at a time. This also means that while moving time forward, each
 * thread might not have the exact same view of what 'now' means. Once
 * the main thread has finished moving its time forward, the worker thread
 * barrier will ensure the timer between main and workers is synchronized.
 *
 * Using an input node in poll-mode has several advantages, including
 * preventing 'unix-epoll-input' to sleep (as it will not sleep if at
 * least one polling node is active). */

#include <vlib/vlib.h>
#include <vlib/time.h>

static f64 vlib_time_virtual_stop;

static uword
vlib_time_virtual_input (vlib_main_t *vm, vlib_node_runtime_t *node,
			 vlib_frame_t *frame)
{
  const f64 next = vlib_time_get_next_timer (vm);
  /* each thread will advance its own time. In case a thread is much faster
   * than another, we must make sure it does not run away... */
  if (vlib_time_now (vm) + next > vlib_time_virtual_stop)
    vlib_node_set_state (vm, node->node_index, VLIB_NODE_STATE_DISABLED);
  else
    vlib_time_adjust (vm, next);
  return 0;
}

VLIB_REGISTER_NODE (vlib_time_virtual_input_node) = {
  .function = vlib_time_virtual_input,
  .type = VLIB_NODE_TYPE_INPUT,
  .name = "virtual-time-input",
  .state = VLIB_NODE_STATE_DISABLED,
};

static clib_error_t *
vlib_time_virtual_adjust_command_fn (vlib_main_t *vm, unformat_input_t *input,
				     vlib_cli_command_t *cmd)
{
  f64 val;

  if (!unformat (input, "%f", &val))
    return clib_error_create ("unknown input `%U'", format_unformat_error,
			      input);

  vlib_time_virtual_stop = vlib_time_now (vm) + val;

  foreach_vlib_main ()
    vlib_node_set_state (this_vlib_main, vlib_time_virtual_input_node.index,
			 VLIB_NODE_STATE_POLLING);

  vlib_worker_thread_barrier_release (vm);
  while ((val = vlib_process_wait_for_event_or_clock (vm, val)) >= 0.001)
    ;
  /* this barrier sync will resynchronize all the clocks, so even if the main
   * thread was faster than some workers, this will make sure the workers will
   * disable their virtual-time-input node on their next iteration (as stop
   * time is reached). If a worker is too slow, there is a slight chance
   * several of its timers expire at the same time at this point. Time will
   * tell... */
  vlib_worker_thread_barrier_sync (vm);
  return 0;
}

VLIB_CLI_COMMAND (vlib_time_virtual_command) = {
  .path = "set clock adjust",
  .short_help = "set clock adjust <nn>",
  .function = vlib_time_virtual_adjust_command_fn,
};