summaryrefslogtreecommitdiffstats
path: root/src/plugins/memif/cli.c
AgeCommit message (Collapse)AuthorFilesLines
2020-12-14misc: move to new pool_foreach macrosDamjan Marion1-2/+1
Type: refactor Change-Id: Ie67dc579e88132ddb1ee4a34cb69f96920101772 Signed-off-by: Damjan Marion <damarion@cisco.com>
2019-07-23api: binary api cleanupDave Barach1-1/+1
Multiple API message handlers call vnet_get_sup_hw_interface(...) without checking the inbound sw_if_index. This can cause a pool_elt_at_index ASSERT in a debug image, and major disorder in a production image. Given that a number of places are coded as follows, add an "api_visible_or_null" variant of vnet_get_sup_hw_interface, which returns NULL given an invalid sw_if_index, or a hidden sw interface: - hw = vnet_get_sup_hw_interface (vnm, sw_if_index); + hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index); if (hw == NULL || memif_device_class.index != hw->dev_class_index) return clib_error_return (0, "not a memif interface"); Rename two existing xxx_safe functions -> xxx_or_null to make it obvious what they return. Type: fix Change-Id: I29996e8d0768fd9e0c5495bd91ff8bedcf2c5697 Signed-off-by: Dave Barach <dave@barachs.net>
2018-09-12Fix create memif socketEd Warnicke1-16/+0
create interface memif [id <id>] [socket-id <socket-id>] ... Can optionally take a socket-id. You create a socket-id with: create memif socket [id <id>] [filename <path>] Unfortunately, this doesn't work because "create memif" was deprecated. It results in: vpp# create memif socket id 0 filename /run/vpp/test.socket command deprecated. Please use 'create interface memif' instead. This fixes it by clipping out the create memif command entirely. Change-Id: If503758706bf758b6cb46e958200527a5856c600 Signed-off-by: Ed Warnicke <hagbard@gmail.com>
2018-04-04memif: zero copy slaveDamjan Marion1-15/+28
Change-Id: I65306fb1f8e39221dd1d8c00737a7fb1c0129ba8 Signed-off-by: Damjan Marion <damarion@cisco.com>
2018-03-22memif: version 2Damjan Marion1-4/+4
In version 1 of the protocol sender was always ring producer and receiver was consumer. In version 2 slave is always producer, and in case of master-to-slave rings, slave is responsible for populating ring with empty buffers. As this is major change, we need to bump version number. In addition, descriptor size is reduced to 16 bytes. This change allows zero-copy-slave operation (to be privided in the separate patch). Change-Id: I02115d232f455ffc05c0bd247f7d03f47252cfaf Signed-off-by: Damjan Marion <damarion@cisco.com> Signed-off-by: Jakub Grajciar <jgrajcia@cisco.com>
2018-02-09memif: fix crash caused by zero pkt len in memif and clear dirty cache while ↵Chun Li1-4/+3
interface reconnect. Change-Id: Ifc7eb2494a22c334d8899422545fca1a4bba4d05 Signed-off-by: Chun Li <chunl2@cisco.com>
2018-01-29memif: Add new API calls to manage memif socket names.Jon Loeliger1-10/+197
New API calls and corresponding CLI commands allow the user to manage the socket filenames for memif connections using: vppctl# create memif id <u32> filename <socket-filename> vppctl# delete memif id <u32> and then referencing it later in a memif interface: vppctl# create memif <u32> socket-id <id> mode <mode> <master|slave> ... Corresponding VAT cli entries have also been added. The default memif socket file at id 0 are still always present. The existing memif create/delete CLI commands have been slightly altered into the new syntax: vppctl# create interface memif ... vppctl# delete interface memif ... Change-Id: If2bdc7eac3d81e1d9011a5869747e52fc5e11639 Signed-off-by: Jon Loeliger <jdl@netgate.com> Signed-off-by: Damjan Marion <damarion@cisco.com>
2017-11-09memif: use clib_socket_t for socket connectionsDamjan Marion1-2/+3
This reverts commit 590acf8fa7af6a8604edd72a32f9f087be52c767. new version includes minor fix for the crash when the interface is deleted. Change-Id: I8fc56eb9145e4d8e1d410206f84e705045898608 Signed-off-by: Damjan Marion <damarion@cisco.com>
2017-11-08memif: do not mask head and tail pointersDamjan Marion1-0/+3
Change-Id: Ie849ab713ff086187c18a91ab32e58207fe94033 Signed-off-by: Damjan Marion <damarion@cisco.com> Signed-off-by: Jakub Grajciar <Jakub.Grajciar@pantheon.tech>
2017-10-04[aarch64] Fixes CLI crashes on dpaa2 platform.Christophe Fontaine1-2/+2
- always use 'va_args' as pointer in all format_* functions - u32 for all 'indent' params as it's declaration was inconsistent Change-Id: Ic5799309a6b104c9b50fec309cba789c8da99e79 Signed-off-by: Christophe Fontaine <christophe.fontaine@enea.com>
2017-09-11memif: mode ip is not settable from binary APISteven1-2/+2
While mode ip is supported via the CLI for creating a memif interface, it is not settable from the binary API due to missing code. While at it, update the help usage to include the missing keyword secret. Change-Id: Ia9c71f4017210a5e1733ce4992fbb566b7d20c1a Signed-off-by: Steven <sluong@cisco.com>
2017-06-19memif: add ip modeDamjan Marion1-1/+4
In IP mode memif interface is L3 point-to-point interfaces and we don't pass l2 header. There is no l2 header rewrite operation and received packets are sent straight to ip4-input / ip6-input nodes. Change-Id: I4177f3fce3004da7ecf14d235006ae053fcf3f09 Signed-off-by: Damjan Marion <damarion@cisco.com>
2017-06-16memif: show memif CLI enhancementSteven1-39/+115
Add optional keywords to show memif to allow display a particular interface and option to display the descriptor tables. The new syntax for the show memif command is now show memif [<interface>] [descriptors] Change-Id: I20696bbea1142bdc152b6e351c6ece24b1cf5500 Signed-off-by: Steven <sluong@cisco.com>
2017-06-12memif: complete refactor of socket handling codeDamjan Marion1-52/+111
Change-Id: I4d41def83a23f13701f1ddcea722d481e4c85cbc Signed-off-by: Damjan Marion <damarion@cisco.com>
2017-05-31memif: multi-queues supportSteven1-3/+28
- Add rx-queues and tx-queues option to the create memif CLI - Add vlib_worker_thread_barrier_sync () to memif_conn_fd_read_ready () as the latter function may disconnect the ring and clean up the shared memory. - On transmit, write the rid (queue number) to the socket. - On receive, read the rid and trigger the interrupt for the corresponding thread. Change-Id: If1c7e26c7124174678f047909cbc33e931eaac8c Signed-off-by: Steven <sluong@cisco.com>
2017-03-22Add memif - packet memory interface for intra-host communicationDamjan Marion1-0/+202
Change-Id: I94c06b07a39f07ceba87bf3e7fcfc70e43231e8a Signed-off-by: Damjan Marion <damarion@cisco.com> Co-Authored-By: Milan Lenco <Milan.Lenco@pantheon.tech>
cial */ .highlight .gd { color: #f92672 } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gi { color: #a6e22e } /* Generic.Inserted */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #75715e } /* Generic.Subheading */ .highlight .kc { color: #66d9ef } /* Keyword.Constant */ .highlight .kd { color: #66d9ef } /* Keyword.Declaration */ .highlight .kn { color: #f92672 } /* Keyword.Namespace */ .highlight .kp { color: #66d9ef } /* Keyword.Pseudo */ .highlight .kr { color: #66d9ef } /* Keyword.Reserved */ .highlight .kt { color: #66d9ef } /* Keyword.Type */ .highlight .ld { color: #e6db74 } /* Literal.Date */ .highlight .m { color: #ae81ff } /* Literal.Number */ .highlight .s { color: #e6db74 } /* Literal.String */ .highlight .na { color: #a6e22e } /* Name.Attribute */ .highlight .nb { color: #f8f8f2 } /* Name.Builtin */ .highlight .nc { color: #a6e22e } /* Name.Class */ .highlight .no { color: #66d9ef } /* Name.Constant */ .highlight .nd { color: #a6e22e } /* Name.Decorator */ .highlight .ni { color: #f8f8f2 } /* Name.Entity */ .highlight .ne { color: #a6e22e } /* Name.Exception */ .highlight .nf { color: #a6e22e } /* Name.Function */ .highlight .nl { color: #f8f8f2 } /* Name.Label */ .highlight .nn { color: #f8f8f2 } /* Name.Namespace */ .highlight .nx { color: #a6e22e } /* Name.Other */ .highlight .py { color: #f8f8f2 } /* Name.Property */ .highlight .nt { color: #f92672 } /* Name.Tag */ .highlight .nv { color: #f8f8f2 } /* Name.Variable */ .highlight .ow { color: #f92672 } /* Operator.Word */ .highlight .w { color: #f8f8f2 } /* Text.Whitespace */ .highlight .mb { color: #ae81ff } /* Literal.Number.Bin */ .highlight .mf { color: #ae81ff } /* Literal.Number.Float */ .highlight .mh { color: #ae81ff } /* Literal.Number.Hex */ .highlight .mi { color: #ae81ff } /* Literal.Number.Integer */ .highlight .mo { color: #ae81ff } /* Literal.Number.Oct */ .highlight .sa { color: #e6db74 } /* Literal.String.Affix */ .highlight .sb { color: #e6db74 } /* Literal.String.Backtick */ .highlight .sc { color: #e6db74 } /* Literal.String.Char */ .highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */ .highlight .sd { color: #e6db74 } /* Literal.String.Doc */ .highlight .s2 { color: #e6db74 } /* Literal.String.Double */ .highlight .se { color: #ae81ff } /* Literal.String.Escape */ .highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */ .highlight .si { color: #e6db74 } /* Literal.String.Interpol */ .highlight .sx { color: #e6db74 } /* Literal.String.Other */ .highlight .sr { color: #e6db74 } /* Literal.String.Regex */ .highlight .s1 { color: #e6db74 } /* Literal.String.Single */ .highlight .ss { color: #e6db74 } /* Literal.String.Symbol */ .highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #a6e22e } /* Name.Function.Magic */ .highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */ .highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */ .highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */ .highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */ .highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */ } @media (prefers-color-scheme: light) { .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #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 */ }
/*
 * 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 <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <netinet/in.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <string.h>
#include <vppinfra/clib.h>
#include <vppinfra/vec.h>
#include <vppinfra/hash.h>
#include <vppinfra/bitmap.h>
#include <vppinfra/fifo.h>
#include <vppinfra/time.h>
#include <vppinfra/mheap.h>
#include <vppinfra/heap.h>
#include <vppinfra/pool.h>
#include <vppinfra/format.h>
#include <vppinfra/serialize.h>
#include "svmdb.h"

typedef struct
{
  svmdb_map_args_t map_args;
  int uid, gid;
  uword size;
} svmdbtool_main_t;

svmdbtool_main_t svmdbtool_main;

static inline svmdb_map_args_t *
map_arg_setup (char *chroot_path)
{
  svmdbtool_main_t *sm = &svmdbtool_main;
  svmdb_map_args_t *ma = &sm->map_args;

  clib_memset (ma, 0, sizeof (*ma));
  ma->root_path = chroot_path;
  ma->size = sm->size;
  ma->uid = sm->uid;
  ma->gid = sm->gid;
  return ma;
}

static void
get_string (char *chroot_path, u8 * vbl)
{
  svmdb_client_t *c;
  char *rv;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);

  rv = svmdb_local_get_string_variable (c, (char *) vbl);

  fformat (stdout, "%s\n", rv ? rv : "UNSET");
  vec_free (rv);
  svmdb_unmap (c);
}

static void
set_string (char *chroot_path, u8 * vbl, u8 * value)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);
  svmdb_local_set_string_variable (c, (char *) vbl, (char *) value);
  svmdb_unmap (c);
}

static void
unset_string (char *chroot_path, u8 * vbl)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);
  svmdb_local_unset_string_variable (c, (char *) vbl);
  svmdb_unmap (c);
}

static void
dump_strings (char *chroot_path)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);
  svmdb_local_dump_strings (c);
  svmdb_unmap (c);
}

static void
serialize_strings (char *chroot_path, char *filename)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);
  (void) svmdb_local_serialize_strings (c, filename);
  svmdb_unmap (c);
}

static void
unserialize_strings (char *chroot_path, char *filename)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);
  (void) svmdb_local_unserialize_strings (c, filename);
  svmdb_unmap (c);
}

static void
test_vlib_vec_rate (char *chroot_path, f64 vr)
{
  svmdb_client_t *c;
  f64 *tv = 0;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);

  vec_add1 (tv, vr);

  svmdb_local_set_vec_variable (c, "vlib_vector_rate", (char *) tv,
				sizeof (*tv));
  svmdb_unmap (c);

  vec_free (tv);
}



static void
test_vec (char *chroot_path, u8 * vbl)
{
  svmdb_client_t *c;
  u64 *tv = 0;
  int i;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);

  /* my amp goes to 11 */
  for (i = 0; i < 11; i++)
    {
      vec_add1 (tv, i);
    }

  svmdb_local_set_vec_variable (c, (char *) vbl, (char *) tv, sizeof (tv[0]));
  svmdb_unmap (c);

  vec_free (tv);
}

static void
fake_install (char *chroot_path, u8 * add_value)
{
  svmdb_client_t *c;
  u8 *v = 0;
  u8 **values = 0;
  u8 *oldvalue;
  u8 *value;
  int nitems = 0, i;
  serialize_main_t m;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);

  oldvalue = svmdb_local_get_vec_variable (c, "installed_sw", 1);
  if (oldvalue)
    {
      unserialize_open_data (&m, oldvalue, vec_len (oldvalue));
      nitems = unserialize_likely_small_unsigned_integer (&m);
      for (i = 0; i < nitems; i++)
	{
	  unserialize_cstring (&m, (char **) &value);
	  vec_add1 (values, value);
	}
      vec_free (v);
    }
  nitems++;
  value = format (0, "%s%c", add_value, 0);

  vec_add1 (values, value);

  fformat (stdout, "Resulting installed_sw vector:\n");

  serialize_open_vector (&m, v);
  serialize_likely_small_unsigned_integer (&m, vec_len (values));
  for (i = 0; i < vec_len (values); i++)
    {
      fformat (stdout, "%s\n", values[i]);
      serialize_cstring (&m, (char *) values[i]);
    }

  v = serialize_close_vector (&m);

  svmdb_local_set_vec_variable (c, "installed_sw", v, sizeof (v[0]));
  svmdb_unmap (c);

  for (i = 0; i < vec_len (values); i++)
    vec_free (values[i]);
  vec_free (values);
}

static void
sigaction_handler (int signum, siginfo_t * i, void *notused)
{
  u32 action, opaque;

  action = (u32) (uword) i->si_ptr;
  action >>= 28;
  opaque = (u32) (uword) i->si_ptr;
  opaque &= ~(0xF0000000);

  clib_warning ("signal %d, action %d, opaque %x", signum, action, opaque);
}

static void
test_reg (char *chroot_path, u8 * vbl)
{
  svmdb_client_t *c;
  svmdb_notification_args_t args;
  svmdb_notification_args_t *a = &args;
  struct sigaction sa;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  clib_memset (&sa, 0, sizeof (sa));
  sa.sa_sigaction = sigaction_handler;
  sa.sa_flags = SA_SIGINFO;
  if (sigaction (SIGUSR2, &sa, 0) < 0)
    {
      clib_unix_warning ("sigaction");
      return;
    }

  clib_memset (a, 0, sizeof (*a));

  c = svmdb_map (ma);

  a->add_del = 1 /* add */ ;
  a->nspace = SVMDB_NAMESPACE_STRING;
  a->var = (char *) vbl;
  a->elsize = 1;
  a->signum = SIGUSR2;
  a->action = SVMDB_ACTION_GET;
  a->opaque = 0x0eadbeef;

  svmdb_local_add_del_notification (c, a);

  (void) svmdb_local_get_string_variable (c, (char *) vbl);

  a->add_del = 0;		/* del */
  svmdb_local_add_del_notification (c, a);



  svmdb_unmap (c);
}

static void
unset_vec (char *chroot_path, u8 * vbl)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);

  svmdb_local_unset_vec_variable (c, (char *) vbl);
  svmdb_unmap (c);
}

static void
dump_vecs (char *chroot_path)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);

  svmdb_local_dump_vecs (c);
  svmdb_unmap (c);
}

static void
crash_test (char *chroot_path)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);

  clib_warning ("Grab region mutex and crash deliberately!");
  c->db_rp->mutex_owner_pid = getpid ();
  c->db_rp->mutex_owner_tag = -13;
  pthread_mutex_lock (&c->db_rp->mutex);

  abort ();
}

static void
map_with_size (char *chroot_path, uword size)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  svmdbtool_main.size = size;
  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);

  svmdb_unmap (c);
}

int
main (int argc, char **argv)
{
  unformat_input_t input;
  int parsed = 0;
  u8 *vbl = 0, *value = 0;
  char *chroot_path = 0;
  u8 *chroot_path_u8;
  u8 *filename;
  uword size;
  f64 vr;
  int uid, gid, rv;
  struct passwd _pw, *pw;
  struct group _grp, *grp;
  char *s, buf[128];

  svmdbtool_main.uid = geteuid ();
  svmdbtool_main.gid = getegid ();

  unformat_init_command_line (&input, argv);

  while (unformat_check_input (&input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (&input, "get-string %s", &vbl))
	{
	  get_string (chroot_path, vbl);
	  vec_free (vbl);
	  parsed++;
	}
      else if (unformat (&input, "set-string %s %s", &vbl, &value))
	{
	  set_string (chroot_path, vbl, value);
	  vec_free (vbl);
	  vec_free (value);
	  parsed++;
	}
      else if (unformat (&input, "unset-string %s", &vbl))
	{
	  unset_string (chroot_path, vbl);
	  vec_free (vbl);
	  parsed++;
	}
      else if (unformat (&input, "dump-strings"))
	{
	  dump_strings (chroot_path);
	  parsed++;
	}
      else if (unformat (&input, "unset-vec %s", &vbl))
	{
	  unset_vec (chroot_path, vbl);
	  vec_free (vbl);
	  parsed++;
	}
      else if (unformat (&input, "dump-vecs"))
	{
	  dump_vecs (chroot_path);
	  parsed++;
	}
      else if (unformat (&input, "test-vec %s", &vbl))
	{
	  test_vec (chroot_path, vbl);
	  // vec_free(vbl);
	  parsed++;
	}
      else if (unformat (&input, "vlib-vec-rate %f", &vr))
	{
	  test_vlib_vec_rate (chroot_path, vr);
	  parsed++;
	}
      else if (unformat (&input, "test-reg %s", &vbl))
	{
	  test_reg (chroot_path, vbl);
	  parsed++;
	}
      else if (unformat (&input, "crash-test"))
	{
	  crash_test (chroot_path);
	}
      else if (unformat (&input, "chroot %s", &chroot_path_u8))
	{
	  chroot_path = (char *) chroot_path_u8;
	}
      else if (unformat (&input, "fake-install %s", &value))
	{
	  fake_install (chroot_path, value);
	  parsed++;
	}
      else if (unformat (&input, "size %d", &size))
	{
	  map_with_size (chroot_path, size);
	  parsed++;
	}
      else if (unformat (&input, "uid %d", &uid))
	svmdbtool_main.uid = uid;
      else if (unformat (&input, "gid %d", &gid))
	svmdbtool_main.gid = gid;
      else if (unformat (&input, "uid %s", &s))
	{
	  /* lookup the username */
	  pw = NULL;
	  rv = getpwnam_r (s, &_pw, buf, sizeof (buf), &pw);
	  if (rv < 0)
	    {
	      fformat (stderr, "cannot fetch username %s", s);
	      exit (1);
	    }
	  if (pw == NULL)
	    {
	      fformat (stderr, "username %s does not exist", s);
	      exit (1);
	    }
	  vec_free (s);
	  svmdbtool_main.uid = pw->pw_uid;
	}
      else if (unformat (&input, "gid %s", &s))
	{
	  /* lookup the group name */
	  grp = NULL;
	  rv = getgrnam_r (s, &_grp, buf, sizeof (buf), &grp);
	  if (rv != 0)
	    {
	      fformat (stderr, "cannot fetch group %s", s);
	      exit (1);
	    }
	  if (grp == NULL)
	    {
	      fformat (stderr, "group %s does not exist", s);
	      exit (1);
	    }
	  vec_free (s);
	  svmdbtool_main.gid = grp->gr_gid;
	}
      else if (unformat (&input, "serialize-strings %s", &filename))
	{
	  vec_add1 (filename, 0);
	  serialize_strings (chroot_path, (char *) filename);
	  parsed++;
	}
      else if (unformat (&input, "unserialize-strings %s", &filename))
	{
	  vec_add1 (filename, 0);
	  unserialize_strings (chroot_path, (char *) filename);
	  parsed++;
	}
      else
	{
	  break;
	}
    }

  unformat_free (&input);

  if (!parsed)
    {
      fformat (stdout, "%s: get-string <name> | set-string <name> <value>\n",
	       argv[0]);
      fformat (stdout, "      unset-string <name> | dump-strings\n");
      fformat (stdout, "      test-vec <name> |\n");
      fformat (stdout, "      unset-vec <name> | dump-vecs\n");
      fformat (stdout, "      chroot <prefix> [uid <nnn-or-userid>]\n");
      fformat (stdout, "      [gid <nnn-or-group-name>]\n");
    }

  exit (0);
}

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