1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
|
/*
* 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 void
vl_api_dhcp_client_details_t_handler (vl_api_dhcp_client_details_t * mp)
{
vat_main_t *vam = &vat_main;
vl_api_dhcp_client_t *cp;
vl_api_dhcp_lease_t *lp;
cp = &mp->client;
lp = &mp->lease;
print (vam->ofp, "sw_if_index %d, id '%s'", ntohl (cp->sw_if_index),
cp->id);
print (vam->ofp, "leased address %U, router address %U",
format_ip4_address, &lp->host_address.un,
format_ip4_address, &lp->router_address.un);
}
static int
api_dhcp_client_dump (vat_main_t * vam)
{
vl_api_dhcp_plugin_control_ping_t *mp_ping;
vl_api_dhcp_client_dump_t *mp;
int ret;
M (DHCP_CLIENT_DUMP, mp);
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_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;
}
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:
*/
|