aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/dhcp/dhcp_test.c
blob: a0d6f416e6b127e494dba0b93c09299ea7d90e47 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

@media only all and (prefers-color-scheme: dark) {
.highlight .hll { background-color: #49483e }
.highlight .c { color: #75715e } /* Comment */
.highlight .err { color: #960050; background-color: #1e0010 } /* Error */
.highlight .k { color: #66d9ef } /* Keyword */
.highlight .l { color: #ae81ff } /* Literal */
.highlight .n { color: #f8f8f2 } /* Name */
.highlight .o { color: #f92672 } /* Operator */
.highlight .p { color: #f8f8f2 } /* Punctuation */
.highlight .ch { color: #75715e } /* Comment.Hashbang */
.highlight .cm { color: #75715e } /* Comment.Multiline */
.highlight .cp { color: #75715e } /* Comment.Preproc */
.highlight .cpf { color: #75715e } /* Comment.PreprocFile */
.highlight .c1 { color: #75715e } /* Comment.Single */
.highlight .cs { color: #75715e } /* Comment.Special */
.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.
 */
/*
 * snap_pg.c: packet generator snap interface
 *
 * Copyright (c) 2008 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
 *  
/*
 * 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 <vat/vat.h>
#include <vlibapi/api.h>
#include <vlibmemory/api.h>
#include <vppinfra/error.h>

#include <dhcp/client.h>
#include <dhcp/dhcp_proxy.h>
#include <vnet/ip/ip_format_fns.h>
#include <vnet/ethernet/ethernet_format_fns.h>

/* define message IDs */
#include <dhcp/dhcp.api_enum.h>
#include <dhcp/dhcp.api_types.h>

typedef struct
{
  /* API message ID base */
  u16 msg_id_base;
  vat_main_t *vat_main;
} dhcp_test_main_t;

dhcp_test_main_t dhcp_test_main;

#define __plugin_msg_base dhcp_test_main.msg_id_base
#include <vlibapi/vat_helper_macros.h>

/* Macro to finish up custom dump fns */
#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
#define FINISH                                  \
    vec_add1 (s, 0);                            \
    vl_print (handle, (char *)s);               \
    vec_free (s);                               \
    return handle;

static int
api_dhcp_proxy_config (vat_main_t * vam)
{
  unformat_input_t *i = vam->input;
  vl_api_dhcp_proxy_config_t *mp;
  u32 rx_vrf_id = 0;
  u32 server_vrf_id = 0;
  u8 is_add = 1;
  u8 v4_address_set = 0;
  u8 v6_address_set = 0;
  ip4_address_t v4address;
  ip6_address_t v6address;
  u8 v4_src_address_set = 0;
  u8 v6_src_address_set = 0;
  ip4_address_t v4srcaddress;
  ip6_address_t v6srcaddress;
  int ret;

  /* Parse args required to build the message */
  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "del"))
	is_add = 0;
      else if (unformat (i, "rx_vrf_id %d", &rx_vrf_id))
	;
      else if (unformat (i, "server_vrf_id %d", &server_vrf_id))
	;
      else if (unformat (i, "svr %U", unformat_ip4_address, &v4address))
	v4_address_set = 1;
      else if (unformat (i, "svr %U", unformat_ip6_address, &v6address))
	v6_address_set = 1;
      else if (unformat (i, "src %U", unformat_ip4_address, &v4srcaddress))
	v4_src_address_set = 1;
      else if (unformat (i, "src %U", unformat_ip6_address, &v6srcaddress))
	v6_src_address_set = 1;
      else
	break;
    }

  if (v4_address_set && v6_address_set)
    {
      errmsg ("both v4 and v6 server addresses set");
      return -99;
    }
  if (!v4_address_set && !v6_address_set)
    {
      errmsg ("no server addresses set");
      return -99;
    }

  if (v4_src_address_set && v6_src_address_set)
    {
      errmsg ("both v4 and v6  src addresses set");
      return -99;
    }
  if (!v4_src_address_set && !v6_src_address_set)
    {
      errmsg ("no src addresses set");
      return -99;
    }

  if (!(v4_src_address_set && v4_address_set) &&
      !(v6_src_address_set && v6_address_set))
    {
      errmsg ("no matching server and src addresses set");
      return -99;
    }

  /* Construct the API message */
  M (DHCP_PROXY_CONFIG, mp);

  mp->is_add = is_add;
  mp->rx_vrf_id = ntohl (rx_vrf_id);
  mp->server_vrf_id = ntohl (server_vrf_id);
  if (v6_address_set)
    {
      clib_memcpy (&mp->dhcp_server.un, &v6address, sizeof (v6address));
      clib_memcpy (&mp->dhcp_src_address.un, &v6srcaddress,
		   sizeof (v6address));
    }
  else
    {
      clib_memcpy (&mp->dhcp_server.un, &v4address, sizeof (v4address));
      clib_memcpy (&mp->dhcp_src_address.un, &v4srcaddress,
		   sizeof (v4address));
    }

  /* send it... */
  S (mp);

  /* Wait for a reply, return good/bad news  */
  W (ret);
  return ret;
}

#define vl_api_dhcp_proxy_details_t_endian vl_noop_handler
#define vl_api_dhcp_proxy_details_t_print vl_noop_handler

static void
vl_api_dhcp_proxy_details_t_handler (vl_api_dhcp_proxy_details_t * mp)
{
  vat_main_t *vam = &vat_main;
  u32 i, count = mp->count;
  vl_api_dhcp_server_t *s;

  if (mp->is_ipv6)
    print (vam->ofp,
	   "RX Table-ID %d, Source Address %U, VSS Type %d, "
	   "VSS ASCII VPN-ID '%s', VSS RFC2685 VPN-ID (oui:id) %d:%d",
	   ntohl (mp->rx_vrf_id),
	   format_ip6_address, mp->dhcp_src_address,
	   mp->vss_type, mp->vss_vpn_ascii_id,
	   ntohl (mp->vss_oui), ntohl (mp->vss_fib_id));
  else
    print (vam->ofp,
	   "RX Table-ID %d, Source Address %U, VSS Type %d, "
	   "VSS ASCII VPN-ID '%s', VSS RFC2685 VPN-ID (oui:id) %d:%d",
	   ntohl (mp->rx_vrf_id),
	   format_ip4_address, mp->dhcp_src_address,
	   mp->vss_type, mp->vss_vpn_ascii_id,
	   ntohl (mp->vss_oui), ntohl (mp->vss_fib_id));

  for (i = 0; i < count; i++)
    {
      s = &mp->servers[i];

      if (mp->is_ipv6)
	print (vam->ofp,
	       " Server Table-ID %d, Server Address %U",
	       ntohl (s->server_vrf_id), format_ip6_address, s->dhcp_server);
      else
	print (vam->ofp,
	       " Server Table-ID %d, Server Address %U",
	       ntohl (s->server_vrf_id), format_ip4_address, s->dhcp_server);
    }
}

static int
api_dhcp_proxy_dump (vat_main_t * vam)
{
  unformat_input_t *i = vam->input;
  vl_api_dhcp_plugin_control_ping_t *mp_ping;
  vl_api_dhcp_proxy_dump_t *mp;
  u8 is_ipv6 = 0;
  int ret;

  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "ipv6"))
	is_ipv6 = 1;
      else
	{
	  clib_warning ("parse error '%U'", format_unformat_error, i);
	  return -99;
	}
    }

  M (DHCP_PROXY_DUMP, mp);

  mp->is_ip6 = is_ipv6;
  S (mp);

  /* Use a control ping for synchronization */
  MPING (DHCP_PLUGIN_CONTROL_PING, mp_ping);
  S (mp_ping);

  W (ret);
  return ret;
}

static int
api_dhcp_proxy_set_vss (vat_main_t * vam)
{
  unformat_input_t *i = vam->input;
  vl_api_dhcp_proxy_set_vss_t *mp;
  u8 is_ipv6 = 0;
  u8 is_add = 1;
  u32 tbl_id = ~0;
  u8 vss_type = VSS_TYPE_DEFAULT;
  u8 *vpn_ascii_id = 0;
  u32 oui = 0;
  u32 fib_id = 0;
  int ret;

  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "tbl_id %d", &tbl_id))
	;
      else if (unformat (i, "vpn_ascii_id %s", &vpn_ascii_id))
	vss_type = VSS_TYPE_ASCII;
      else if (unformat (i, "fib_id %d", &fib_id))
	vss_type = VSS_TYPE_VPN_ID;
      else if (unformat (i, "oui %d", &oui))
	vss_type = VSS_TYPE_VPN_ID;
      else if (unformat (i, "ipv6"))
	is_ipv6 = 1;
      else if (unformat (i, "del"))
	is_add = 0;
      else
	break;
    }

  if (tbl_id == ~0)
    {
      errmsg ("missing tbl_id ");
      vec_free (vpn_ascii_id);
      return -99;
    }

  if ((vpn_ascii_id) && (vec_len (vpn_ascii_id) > 128))
    {
      errmsg ("vpn_ascii_id cannot be longer than 128 ");
      vec_free (vpn_ascii_id);
      return -99;
    }

  M (DHCP_PROXY_SET_VSS, mp);
  mp->tbl_id = ntohl (tbl_id);
  mp->vss_type = vss_type;
  if (vpn_ascii_id)
    {
      clib_memcpy (mp->vpn_ascii_id, vpn_ascii_id, vec_len (vpn_ascii_id));
      mp->vpn_ascii_id[vec_len (vpn_ascii_id)] = 0;
    }
  mp->vpn_index = ntohl (fib_id);
  mp->oui = ntohl (oui);
  mp->is_ipv6 = is_ipv6;
  mp->is_add = is_add;

  S (mp);
  W (ret);

  vec_free (vpn_ascii_id);
  return ret;
}

static int
api_dhcp_client_config (vat_main_t * vam)
{
  unformat_input_t *i = vam->input;
  vl_api_dhcp_client_config_t *mp;
  u32 sw_if_index;
  u8 sw_if_index_set = 0;
  u8 is_add = 1;
  u8 *hostname = 0;
  u8 disable_event = 0;
  int ret;

  /* Parse args required to build the message */
  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "del"))
	is_add = 0;
      else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "sw_if_index %d", &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "hostname %s", &hostname))
	;
      else if (unformat (i, "disable_event"))
	disable_event = 1;
      else
	break;
    }

  if (sw_if_index_set == 0)
    {
      errmsg ("missing interface name or sw_if_index");
      return -99;
    }

  if (vec_len (hostname) > 63)
    {
      errmsg ("hostname too long");
    }
  vec_add1 (hostname, 0);

  /* Construct the API message */
  M (DHCP_CLIENT_CONFIG, mp);

  mp->is_add = is_add;
  mp->client.sw_if_index = htonl (sw_if_index);
  clib_memcpy (mp->client.hostname, hostname, vec_len (hostname));
  vec_free (hostname);
  mp->client.want_dhcp_event = disable_event ? 0 : 1;
  mp->client.pid = htonl (getpid ());

  /* send it... */
  S (mp);

  /* Wait for a reply, return good/bad news  */
  W (ret);
  return ret;
}

static int
api_want_dhcp6_reply_events (vat_main_t * vam)
{
  return -1;
}

static int
api_want_dhcp6_pd_reply_events (vat_main_t * vam)
{
  return -1;
}

static int
api_dhcp6_send_client_message (vat_main_t * vam)
{
  return -1;
}

static int
api_dhcp6_pd_send_client_message (vat_main_t * vam)
{
  return -1;
}

static int
api_dhcp_client_dump (vat_main_t * vam)
{
  return -1;
}

static int
api_dhcp6_duid_ll_set (vat_main_t * vam)
{
  return -1;
}

static int
api_dhcp6_clients_enable_disable (vat_main_t * vam)
{
  return -1;
}

static int
api_dhcp_plugin_control_ping (vat_main_t * vam)
{
  return -1;
}

static int
api_dhcp_plugin_get_version (vat_main_t * vam)
{
  return -1;
}

#define vl_api_dhcp_client_details_t_handler vl_noop_handler

static void
  vl_api_dhcp_plugin_get_version_reply_t_handler
  (vl_api_dhcp_plugin_get_version_reply_t * mp)
{
  vat_main_t *vam = dhcp_test_main.vat_main;
  clib_warning ("DHCP plugin version: %d.%d", ntohl (mp->major),
		ntohl (mp->minor));
  vam->result_ready = 1;
}

static void
  vl_api_dhcp_plugin_control_ping_reply_t_handler
  (vl_api_dhcp_plugin_control_ping_reply_t * mp)
{
  vat_main_t *vam = dhcp_test_main.vat_main;
  i32 retval = ntohl (mp->retval);
  if (vam->async_mode)
    {
      vam->async_errors += (retval < 0);
    }
  else
    {
      vam->retval = retval;
      vam->result_ready = 1;
    }
}

#include <dhcp/dhcp.api_test.c>

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