aboutsummaryrefslogtreecommitdiffstats
path: root/test/test_l2bd_multi_instance.py
AgeCommit message (Collapse)AuthorFilesLines
2022-02-17tests: make tests less make dependentKlement Sekera1-1/+1
Implement command line argument parsing instead of passing arguments via environment variables. Add script for running tests without having to invoke make. Deprecate running tests via make. Type: improvement Change-Id: I2e3054a61a2ae25d460e9be00be7d7705fbf943e Signed-off-by: Klement Sekera <ksekera@cisco.com> Signed-off-by: Dave Wallace <dwallacelf@gmail.com>
2019-12-23tests: TestL2bdMultiInst - break serial dependency on testsPaul Vinciguerra1-10/+15
enable the tests to run out of order/enable running an individual test. Before: [gw1] [ 20%] FAILED test/test_l2bd_multi_instance.py::TestL2bdMultiInst::test_l2bd_inst_02 [gw0] [ 40%] PASSED test/test_l2bd_multi_instance.py::TestL2bdMultiInst::test_l2bd_inst_01 [gw1] [ 60%] PASSED test/test_l2bd_multi_instance.py::TestL2bdMultiInst::test_l2bd_inst_04 [gw0] [ 80%] FAILED test/test_l2bd_multi_instance.py::TestL2bdMultiInst::test_l2bd_inst_03 [gw1] [100%] SKIPPED test/test_l2bd_multi_instance.py::TestL2bdMultiInst::test_l2bd_inst_05 ------- After: [gw1] [ 20%] PASSED test/test_l2bd_multi_instance.py::TestL2bdMultiInst::test_l2bd_inst_02 [gw0] [ 40%] PASSED test/test_l2bd_multi_instance.py::TestL2bdMultiInst::test_l2bd_inst_01 [gw1] [ 60%] PASSED test/test_l2bd_multi_instance.py::TestL2bdMultiInst::test_l2bd_inst_04 [gw0] [ 80%] PASSED test/test_l2bd_multi_instance.py::TestL2bdMultiInst::test_l2bd_inst_03 [gw1] [100%] PASSED test/test_l2bd_multi_instance.py::TestL2bdMultiInst::test_l2bd_inst_05 Type: test Change-Id: Ie40eb310f5fccacf854c364aa017891bce9b9372 Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
2019-11-05misc: Fix python scripts shebang lineRenato Botelho do Couto1-1/+1
Type: fix Since CentOS 8, RPM build script doesn't accept '#!/usr/bin/env python' as a valid shebang line. It requires scripts to explicitly chose between python2 or python3. Change all to use python3 as suggested by Paul Vinciguerra. Depends-On: https://gerrit.fd.io/r/23170 Signed-off-by: Renato Botelho do Couto <renato@netgate.com> Change-Id: Ie72af9f60fd0609e07f05b70f8d96e738b2754d1
2019-04-10Tests Cleanup: Fix missing calls to setUpClass/tearDownClass.Paul Vinciguerra1-0/+4
Continuation/Part 2 of https://gerrit.fd.io/r/#/c/17092/ Change-Id: Id0122d84eaf2c05d29e5be63a594d5e528ee7c9a Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
2019-03-11vpp_papi_provider: Remove more wrapper functions.Ole Troan1-5/+6
Split this work up into pieces. Please don't add new wrappers to vpp_papi_provider.py. Change-Id: I0f8f2afc4cd2bba07ea70ddecea2d7319f7b2e10 Signed-off-by: Ole Troan <ot@cisco.com>
2019-03-07Tests: Refactor payload_to_info()Paul Vinciguerra1-1/+1
All callers of payload_to_info were required to wrap payload with str(). Refactor to call scapy's payload.load for raw payloads or specify the specific fieldname. Change-Id: I1c80599d4df8dc129dbb8274733afaad406d5bcf Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
2018-12-20Tests: Cleanup @skip decorator.Paul Vinciguerra1-1/+1
The runnning environment is static as of module load time, so only evalute the conditions once at module load time. Track-by: VPP-1518 Change-Id: I73b0d17ae1ff90789e70307f168d43921829aec8 Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
2017-09-07make test: disable L2BD Multi-instance test 5Florin Coras1-1/+2
Change-Id: Iba44aec60a74ada5add41ecf00b25dc44f3ad3a3 Signed-off-by: Florin Coras <fcoras@cisco.com>
2017-06-27L2-LEARN:fix l2fib entry seq num not updated on hit (VPP-888)Eyal Bari1-29/+29
fixed instability in l2bd_multi_instnce test - sometimes failing with extra packets captured it appears l2-learn was not updating hit entries but rather a copy of them. if the ager did not have a chance to run before the test was running the learning cycle - entries were not updated with the packet's seq num - causing packets to flood when hitting the stale seq_num in l2-fwd - hence the extra packets fixed handling of filter entries revert workaround for instability in test Change-Id: I16d918e6310a5bf40bad5b7335b2140c2867cb71 Signed-off-by: Eyal Bari <ebari@cisco.com> (cherry picked from commit 25ff2ea3a31e422094f6d91eab46222a29a77c4b)
2017-06-21L2-VTR: add vtr testsEyal Bari1-30/+30
re-enable l2 fib flush tests reorder l2bd multi instance tests - move flags test as last enabling of uu-flood will now flood when entry is stale Change-Id: I052663ec3eb4acee5f296fb7525dd535924e0003 Signed-off-by: Eyal Bari <ebari@cisco.com>
2017-05-10L2BD/TEST:fix l2bd multiinstance testEyal Bari1-104/+94
Change-Id: If864182ec656cc6c6353be642e22910a4fc89870 Signed-off-by: Eyal Bari <ebari@cisco.com>
2017-01-11make test: improve documentation and PEP8 complianceKlement Sekera1-6/+7
Change-Id: Ib4f0353aab6112fcc3c3d8f0bcbed5bc4b567b9b Signed-off-by: Klement Sekera <ksekera@cisco.com>
2016-12-23make test: improve handling of packet capturesKlement Sekera1-13/+2
Perform accounting of expected packets based on created packet infos. Use this accounting info to automatically expect (and verify) the correct number of packets to be captured. Automatically retry the read of the capture file if scapy raises an exception while doing so to handle rare cases when capture file is read while only partially written during busy wait. Don't fail assert_nothing_captured if only junk packets arrived. Change-Id: I16ec2e9410ef510d313ec16b7e13c57d0b2a63f5 Signed-off-by: Klement Sekera <ksekera@cisco.com>
2016-12-16make test: improve robustness and performanceKlement Sekera1-11/+11
Introduce an API which asserts empty capture for interface. Throw exception in old API if the capture does not exist, thus making it clear if the test expects packets to arrive or not. Improve performance by not doing sleeps after starting the packet generator, rather lazily deleting captures when needed. Fix wrong usage of packet.show() in various tests. Change-Id: I456cb23316eef99b3f35f80344fe595c4db9a21c Signed-off-by: Klement Sekera <ksekera@cisco.com>
2016-12-13make test: Use VXLAN built in scapy 2.3.3Matej Klotton1-9/+10
- fix documentation issues. - fix mpls test. Change-Id: Ieef6b4b5e4aca99e89bd03e45a991be89d42adba Signed-off-by: Matej Klotton <mklotton@cisco.com>
2016-12-06SPAN API: Fix various errors making SPAN break make tests.Ole Troan1-6/+1
- s/l2/span in span_api.c in foreach macro - Not installing .json from Makefile.am Change-Id: I2469fe01138d62e044b8262cdb5a6e3b009bb43e Signed-off-by: Ole Troan <ot@cisco.com>
2016-12-06API: Adapt make test to Python API changes.Ole Troan1-0/+5
Change the test wrapper script for the updated Python API. All tests but the L2BD multi instance runs fine. That is currently skipped. I see intermittent failures when an MLD message is received before the ND NA in MPLS and IPV6 FIB tests. Change-Id: If809877c9abdf596dbb0a419ce5429552f63d212 Signed-off-by: Ole Troan <ot@cisco.com>
2016-12-05test: l2bd instance multi-context correctionJan1-29/+21
- small correction of docstrings - fix of create_pg_interface Change-Id: I1958bd5ddaddaa2f7e6cbb18b0076e59e86d1e68 Signed-off-by: Jan Gelety <jgelety@cisco.com>
2016-12-02test: l2bd instances multi-context test (CSIT-479)Jan1-0/+505
- add/update/delete L2BD instances and verify results by API command bridge_domain_dump and by traffic where applicable Change-Id: Ic9d7f7b5f6f10e5df7053f27cbc87f653704dab1 Signed-off-by: Jan <jgelety@cisco.com>
} /* 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.
 */
/*
  Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus

  Permission is hereby granted, free of charge, to any person obtaining
  a copy of this software and associated documentation files (the
  "Software"), to deal in the Software without restriction, including
  without limitation the rights to use, copy, modify, merge, publish,
  distribute, sublicense, and/or sell copies of the Software, and to
  permit persons to whom the Software is furnished to do so, subject to
  the following conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#ifdef CLIB_LINUX_KERNEL
#include <linux/unistd.h>
#endif

#ifdef CLIB_UNIX
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <vppinfra/time.h>
#endif

#include <vppinfra/random.h>
#include <vppinfra/mem.h>
#include <vppinfra/hash.h>
#include <vppinfra/error.h>
#include <vppinfra/format.h>
#include <vppinfra/bitmap.h>

static int verbose;
#define if_verbose(format,args...) \
  if (verbose) { clib_warning(format, ## args); }

typedef struct
{
  int n_iterations;

  int n_iterations_per_print;

  /* Number of pairs to insert into hash. */
  int n_pairs;

  /* True to validate correctness of hash functions. */
  int n_iterations_per_validate;

  /* Non-zero if hash table size is to be fixed. */
  int fixed_hash_size;

  /* Verbosity level for hash formats. */
  int verbose;

  /* Random number seed. */
  u32 seed;
} hash_test_t;

static clib_error_t *
hash_next_test (word * h)
{
  hash_next_t hn = { 0 };
  hash_pair_t *p0, *p1;
  clib_error_t *error = 0;

  /* *INDENT-OFF* */
  hash_foreach_pair (p0, h, {
    p1 = hash_next (h, &hn);
    error = CLIB_ERROR_ASSERT (p0 == p1);
    if (error)
      break;
  });
  /* *INDENT-ON* */

  if (!error)
    error = CLIB_ERROR_ASSERT (!hash_next (h, &hn));

  return error;
}

static u8 *
test1_format (u8 * s, va_list * args)
{
  void *CLIB_UNUSED (user_arg) = va_arg (*args, void *);
  void *v = va_arg (*args, void *);
  hash_pair_t *p = va_arg (*args, hash_pair_t *);
  hash_t *h = hash_header (v);

  return format (s, "0x%8U -> 0x%8U",
		 format_hex_bytes, &p->key, sizeof (p->key),
		 format_hex_bytes, &p->value[0], hash_value_bytes (h));
}

static clib_error_t *
test_word_key (hash_test_t * ht)
{
  word *h = 0;
  word i, j;

  word *keys = 0, *vals = 0;
  uword *is_inserted = 0;

  clib_error_t *error = 0;

  vec_resize (keys, ht->n_pairs);
  vec_resize (vals, vec_len (keys));

  h = hash_create (ht->fixed_hash_size, sizeof (vals[0]));

  hash_set_pair_format (h, test1_format, 0);
  if (ht->fixed_hash_size)
    hash_set_flags (h, HASH_FLAG_NO_AUTO_GROW | HASH_FLAG_NO_AUTO_SHRINK);

  {
    uword *unique = 0;
    u32 k;

    for (i = 0; i < vec_len (keys); i++)
      {
	do
	  {
	    k = random_u32 (&ht->seed) & 0xfffff;
	  }
	while (clib_bitmap_get (unique, k));
	unique = clib_bitmap_ori (unique, k);
	keys[i] = k;
	vals[i] = i;
      }

    clib_bitmap_free (unique);
  }

  for (i = 0; i < ht->n_iterations; i++)
    {
      u32 vi = random_u32 (&ht->seed) % vec_len (keys);

      if (clib_bitmap_get (is_inserted, vi))
	hash_unset (h, keys[vi]);
      else
	hash_set (h, keys[vi], vals[vi]);

      is_inserted = clib_bitmap_xori (is_inserted, vi);

      if (ht->n_iterations_per_print > 0
	  && ((i + 1) % ht->n_iterations_per_print) == 0)
	if_verbose ("iteration %d\n  %U", i + 1, format_hash, h, ht->verbose);

      if (ht->n_iterations_per_validate == 0
	  || (i + 1) % ht->n_iterations_per_validate)
	continue;

      {
	hash_pair_t *p;
	uword ki;

	  /* *INDENT-OFF* */
	  hash_foreach_pair (p, h, {
	      ki = p->value[0];
	      ASSERT (keys[ki] == p->key);
	  });
	  /* *INDENT-ON* */
      }

      clib_mem_validate ();

      if ((error = hash_validate (h)))
	goto done;

      for (j = 0; j < vec_len (keys); j++)
	{
	  uword *v;
	  v = hash_get (h, keys[j]);
	  if ((error =
	       CLIB_ERROR_ASSERT (clib_bitmap_get (is_inserted, j) ==
				  (v != 0))))
	    goto done;
	  if (v)
	    {
	      if ((error = CLIB_ERROR_ASSERT (v[0] == vals[j])))
		goto done;
	    }
	}
    }

  if ((error = hash_next_test (h)))
    goto done;

  if_verbose ("%U", format_hash, h, ht->verbose);

  for (i = 0; i < vec_len (keys); i++)
    {
      if (!clib_bitmap_get (is_inserted, i))
	continue;

      hash_unset (h, keys[i]);
      is_inserted = clib_bitmap_xori (is_inserted, i);

      if (ht->n_iterations_per_validate == 0
	  || (i + 1) % ht->n_iterations_per_validate)
	continue;

      clib_mem_validate ();

      if ((error = hash_validate (h)))
	goto done;

      for (j = 0; j < vec_len (keys); j++)
	{
	  uword *v;
	  v = hash_get (h, keys[j]);
	  if ((error =
	       CLIB_ERROR_ASSERT (clib_bitmap_get (is_inserted, j) ==
				  (v != 0))))
	    goto done;
	  if (v)
	    {
	      if ((error = CLIB_ERROR_ASSERT (v[0] == vals[j])))
		goto done;
	    }
	}
    }

done:
  hash_free (h);
  vec_free (keys);
  vec_free (vals);
  clib_bitmap_free (is_inserted);

  if (verbose)
    fformat (stderr, "%U\n", format_clib_mem_usage, /* verbose */ 0);

  return error;
}

static u8 *
test2_format (u8 * s, va_list * args)
{
  void *CLIB_UNUSED (user_arg) = va_arg (*args, void *);
  void *v = va_arg (*args, void *);
  hash_pair_t *p = va_arg (*args, hash_pair_t *);
  hash_t *h = hash_header (v);

  return format (s, "0x%8U <- %v",
		 format_hex_bytes, &p->value[0], hash_value_bytes (h),
		 p->key);
}

static clib_error_t *
test_string_key (hash_test_t * ht)
{
  word i, j;

  u8 **keys = 0;
  word *vals = 0;
  uword *is_inserted = 0;

  word *h = 0;

  clib_error_t *error = 0;

  vec_resize (keys, ht->n_pairs);
  vec_resize (vals, vec_len (keys));

  h =
    hash_create_vec (ht->fixed_hash_size, sizeof (keys[0][0]),
		     sizeof (uword));
  hash_set_pair_format (h, test2_format, 0);
  if (ht->fixed_hash_size)
    hash_set_flags (h, HASH_FLAG_NO_AUTO_SHRINK | HASH_FLAG_NO_AUTO_GROW);

  for (i = 0; i < vec_len (keys); i++)
    {
      keys[i] = random_string (&ht->seed, 5 + (random_u32 (&ht->seed) & 0xf));
      keys[i] = format (keys[i], "%x", i);
      vals[i] = random_u32 (&ht->seed);
    }

  for (i = 0; i < ht->n_iterations; i++)
    {
      u32 vi = random_u32 (&ht->seed) % vec_len (keys);

      if (clib_bitmap_get (is_inserted, vi))
	hash_unset_mem (h, keys[vi]);
      else
	hash_set_mem (h, keys[vi], vals[vi]);

      is_inserted = clib_bitmap_xori (is_inserted, vi);

      if (ht->n_iterations_per_print > 0
	  && ((i + 1) % ht->n_iterations_per_print) == 0)
	if_verbose ("iteration %d\n  %U", i + 1, format_hash, h, ht->verbose);

      if (ht->n_iterations_per_validate == 0
	  || (i + 1) % ht->n_iterations_per_validate)
	continue;

      clib_mem_validate ();

      if ((error = hash_validate (h)))
	goto done;

      for (j = 0; j < vec_len (keys); j++)
	{
	  uword *v;
	  v = hash_get_mem (h, keys[j]);
	  if ((error =
	       CLIB_ERROR_ASSERT (clib_bitmap_get (is_inserted, j) ==
				  (v != 0))))
	    goto done;
	  if (v)
	    {
	      if ((error = CLIB_ERROR_ASSERT (v[0] == vals[j])))
		goto done;
	    }
	}
    }

  if ((error = hash_next_test (h)))
    goto done;

  if_verbose ("%U", format_hash, h, ht->verbose);

  for (i = 0; i < vec_len (keys); i++)
    {
      if (!clib_bitmap_get (is_inserted, i))
	continue;

      hash_unset_mem (h, keys[i]);
      is_inserted = clib_bitmap_xori (is_inserted, i);

      if (ht->n_iterations_per_validate == 0
	  || (i + 1) % ht->n_iterations_per_validate)
	continue;

      clib_mem_validate ();

      if ((error = hash_validate (h)))
	goto done;

      for (j = 0; j < vec_len (keys); j++)
	{
	  uword *v;
	  v = hash_get_mem (h, keys[j]);
	  if ((error =
	       CLIB_ERROR_ASSERT (clib_bitmap_get (is_inserted, j) ==
				  (v != 0))))
	    goto done;
	  if (v)
	    {
	      if ((error = CLIB_ERROR_ASSERT (v[0] == vals[j])))
		goto done;
	    }
	}
    }

done:
  hash_free (h);
  vec_free (vals);
  clib_bitmap_free (is_inserted);

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

  if (verbose)
    fformat (stderr, "%U\n", format_clib_mem_usage, /* verbose */ 0);

  return error;
}

int
test_hash_main (unformat_input_t * input)
{
  hash_test_t _ht = { 0 }, *ht = &_ht;
  clib_error_t *error;

  ht->n_iterations = 100;
  ht->n_pairs = 10;
  ht->fixed_hash_size = 0;	/* zero means non-fixed size */

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      if (0 == unformat (input, "iter %d", &ht->n_iterations)
	  && 0 == unformat (input, "print %d", &ht->n_iterations_per_print)
	  && 0 == unformat (input, "elts %d", &ht->n_pairs)
	  && 0 == unformat (input, "size %d", &ht->fixed_hash_size)
	  && 0 == unformat (input, "seed %d", &ht->seed)
	  && 0 == unformat (input, "verbose %=", &ht->verbose, 1)
	  && 0 == unformat (input, "valid %d",
			    &ht->n_iterations_per_validate))
	{
	  clib_warning ("unknown input `%U'", format_unformat_error, input);
	  return 1;
	}
    }

  if (!ht->seed)
    ht->seed = random_default_seed ();

  if_verbose ("testing %d iterations, seed %d", ht->n_iterations, ht->seed);

  error = test_word_key (ht);
  if (error)
    clib_error_report (error);

  error = test_string_key (ht);
  if (error)
    clib_error_report (error);

  return 0;
}

#ifdef CLIB_UNIX
int
main (int argc, char *argv[])
{
  unformat_input_t i;
  int ret;

  clib_mem_init (0, 3ULL << 30);

  verbose = (argc > 1);
  unformat_init_command_line (&i, argv);
  ret = test_hash_main (&i);
  unformat_free (&i);

  return ret;
}
#endif /* CLIB_UNIX */

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