282 lines
6.9 KiB
C
282 lines
6.9 KiB
C
/*
|
|
* Copyright 2020 Rubicon Communications, LLC.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <sys/socket.h>
|
|
#include <linux/if.h>
|
|
|
|
#include <vnet/vnet.h>
|
|
#include <vnet/plugin/plugin.h>
|
|
|
|
#include <vlibapi/api.h>
|
|
#include <vlibmemory/api.h>
|
|
#include <vpp/app/version.h>
|
|
#include <vnet/format_fns.h>
|
|
|
|
#include <lcpng/lcpng_interface.h>
|
|
#include <lcpng/lcpng_if.api_enum.h>
|
|
#include <lcpng/lcpng_if.api_types.h>
|
|
|
|
static u16 lcp_msg_id_base;
|
|
#define REPLY_MSG_ID_BASE lcp_msg_id_base
|
|
#include <vlibapi/api_helper_macros.h>
|
|
|
|
static lip_host_type_t
|
|
api_decode_host_type (vl_api_lcp_itf_host_type_t type)
|
|
{
|
|
if (type == LCP_API_ITF_HOST_TUN)
|
|
return LCP_ITF_HOST_TUN;
|
|
|
|
return LCP_ITF_HOST_TAP;
|
|
}
|
|
|
|
static vl_api_lcp_itf_host_type_t
|
|
api_encode_host_type (lip_host_type_t type)
|
|
{
|
|
if (type == LCP_ITF_HOST_TUN)
|
|
return LCP_API_ITF_HOST_TUN;
|
|
|
|
return LCP_API_ITF_HOST_TAP;
|
|
}
|
|
|
|
static int
|
|
vl_api_lcp_itf_pair_add (u32 phy_sw_if_index, lip_host_type_t lip_host_type,
|
|
u8 *mp_host_if_name, size_t sizeof_host_if_name,
|
|
u8 *mp_netns, size_t sizeof_mp_netns,
|
|
u32 *host_sw_if_index_p)
|
|
{
|
|
u8 *host_if_name, *netns;
|
|
int host_len, netns_len, rv;
|
|
|
|
host_if_name = netns = 0;
|
|
|
|
/* lcp_itf_pair_create expects vec of u8 */
|
|
host_len = clib_strnlen ((char *) mp_host_if_name, sizeof_host_if_name - 1);
|
|
vec_add (host_if_name, mp_host_if_name, host_len);
|
|
vec_add1 (host_if_name, 0);
|
|
|
|
netns_len = clib_strnlen ((char *) mp_netns, sizeof_mp_netns - 1);
|
|
vec_add (netns, mp_netns, netns_len);
|
|
vec_add1 (netns, 0);
|
|
|
|
rv = lcp_itf_pair_create (phy_sw_if_index, host_if_name, lip_host_type,
|
|
netns, host_sw_if_index_p);
|
|
|
|
vec_free (host_if_name);
|
|
vec_free (netns);
|
|
|
|
return rv;
|
|
}
|
|
|
|
static void
|
|
vl_api_lcp_itf_pair_add_del_t_handler (vl_api_lcp_itf_pair_add_del_t *mp)
|
|
{
|
|
u32 phy_sw_if_index;
|
|
vl_api_lcp_itf_pair_add_del_reply_t *rmp;
|
|
lip_host_type_t lip_host_type;
|
|
int rv;
|
|
|
|
VALIDATE_SW_IF_INDEX_END (mp);
|
|
|
|
phy_sw_if_index = mp->sw_if_index;
|
|
lip_host_type = api_decode_host_type (mp->host_if_type);
|
|
if (mp->is_add)
|
|
{
|
|
rv = vl_api_lcp_itf_pair_add (
|
|
phy_sw_if_index, lip_host_type, mp->host_if_name,
|
|
sizeof (mp->host_if_name), mp->netns, sizeof (mp->netns), NULL);
|
|
}
|
|
else
|
|
{
|
|
rv = lcp_itf_pair_delete (phy_sw_if_index);
|
|
}
|
|
|
|
BAD_SW_IF_INDEX_LABEL;
|
|
REPLY_MACRO_END (VL_API_LCP_ITF_PAIR_ADD_DEL_REPLY);
|
|
}
|
|
|
|
static void
|
|
vl_api_lcp_itf_pair_add_del_v2_t_handler (vl_api_lcp_itf_pair_add_del_v2_t *mp)
|
|
{
|
|
u32 phy_sw_if_index, host_sw_if_index = ~0;
|
|
vl_api_lcp_itf_pair_add_del_v2_reply_t *rmp;
|
|
lip_host_type_t lip_host_type;
|
|
int rv;
|
|
|
|
VALIDATE_SW_IF_INDEX_END (mp);
|
|
|
|
phy_sw_if_index = mp->sw_if_index;
|
|
lip_host_type = api_decode_host_type (mp->host_if_type);
|
|
if (mp->is_add)
|
|
{
|
|
rv = vl_api_lcp_itf_pair_add (phy_sw_if_index, lip_host_type,
|
|
mp->host_if_name,
|
|
sizeof (mp->host_if_name), mp->netns,
|
|
sizeof (mp->netns), &host_sw_if_index);
|
|
}
|
|
else
|
|
{
|
|
rv = lcp_itf_pair_delete (phy_sw_if_index);
|
|
}
|
|
|
|
BAD_SW_IF_INDEX_LABEL;
|
|
REPLY_MACRO2_END (VL_API_LCP_ITF_PAIR_ADD_DEL_V2_REPLY,
|
|
{ rmp->host_sw_if_index = host_sw_if_index; });
|
|
}
|
|
|
|
static void
|
|
send_lcp_itf_pair_details (index_t lipi, vl_api_registration_t *rp,
|
|
u32 context)
|
|
{
|
|
vl_api_lcp_itf_pair_details_t *rmp;
|
|
lcp_itf_pair_t *lcp_pair = lcp_itf_pair_get (lipi);
|
|
|
|
REPLY_MACRO_DETAILS4_END (
|
|
VL_API_LCP_ITF_PAIR_DETAILS, rp, context, ({
|
|
rmp->phy_sw_if_index = lcp_pair->lip_phy_sw_if_index;
|
|
rmp->host_sw_if_index = lcp_pair->lip_host_sw_if_index;
|
|
rmp->vif_index = lcp_pair->lip_vif_index;
|
|
rmp->host_if_type = api_encode_host_type (lcp_pair->lip_host_type);
|
|
|
|
memcpy_s (rmp->host_if_name, sizeof (rmp->host_if_name),
|
|
lcp_pair->lip_host_name, vec_len (lcp_pair->lip_host_name));
|
|
rmp->host_if_name[vec_len (lcp_pair->lip_host_name)] = 0;
|
|
|
|
memcpy_s (rmp->netns, sizeof (rmp->netns), lcp_pair->lip_namespace,
|
|
vec_len (lcp_pair->lip_namespace));
|
|
rmp->netns[vec_len (lcp_pair->lip_namespace)] = 0;
|
|
}));
|
|
}
|
|
|
|
static void
|
|
vl_api_lcp_itf_pair_get_t_handler (vl_api_lcp_itf_pair_get_t *mp)
|
|
{
|
|
vl_api_lcp_itf_pair_get_reply_t *rmp;
|
|
i32 rv = 0;
|
|
|
|
REPLY_AND_DETAILS_MACRO_END (
|
|
VL_API_LCP_ITF_PAIR_GET_REPLY, lcp_itf_pair_pool,
|
|
({ send_lcp_itf_pair_details (cursor, rp, mp->context); }));
|
|
}
|
|
|
|
static void
|
|
vl_api_lcp_itf_pair_get_v2_t_handler (vl_api_lcp_itf_pair_get_v2_t *mp)
|
|
{
|
|
vl_api_lcp_itf_pair_get_v2_reply_t *rmp;
|
|
i32 rv = 0;
|
|
|
|
if (mp->sw_if_index == ~0)
|
|
{
|
|
// Does this actually work?
|
|
REPLY_AND_DETAILS_MACRO_END (
|
|
VL_API_LCP_ITF_PAIR_GET_REPLY, lcp_itf_pair_pool,
|
|
({ send_lcp_itf_pair_details (cursor, rp, mp->context); }));
|
|
}
|
|
else
|
|
{
|
|
VALIDATE_SW_IF_INDEX_END (mp);
|
|
|
|
u32 pair_index = lcp_itf_pair_find_by_phy (mp->sw_if_index);
|
|
if (pair_index == INDEX_INVALID)
|
|
{
|
|
rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
|
|
goto bad_sw_if_index;
|
|
}
|
|
send_lcp_itf_pair_details (
|
|
pair_index, vl_api_client_index_to_registration (mp->client_index),
|
|
mp->context);
|
|
|
|
BAD_SW_IF_INDEX_LABEL;
|
|
REPLY_MACRO2_END (VL_API_LCP_ITF_PAIR_GET_V2_REPLY,
|
|
({ rmp->cursor = ~0; }));
|
|
}
|
|
}
|
|
|
|
static void
|
|
vl_api_lcp_default_ns_set_t_handler (vl_api_lcp_default_ns_set_t *mp)
|
|
{
|
|
vl_api_lcp_default_ns_set_reply_t *rmp;
|
|
int rv;
|
|
|
|
mp->netns[LCP_NS_LEN - 1] = 0;
|
|
rv = lcp_set_default_ns (mp->netns);
|
|
|
|
REPLY_MACRO (VL_API_LCP_DEFAULT_NS_SET_REPLY);
|
|
}
|
|
|
|
static void
|
|
vl_api_lcp_default_ns_get_t_handler (vl_api_lcp_default_ns_get_t *mp)
|
|
{
|
|
vl_api_lcp_default_ns_get_reply_t *rmp;
|
|
vl_api_registration_t *reg;
|
|
char *ns;
|
|
|
|
reg = vl_api_client_index_to_registration (mp->client_index);
|
|
if (!reg)
|
|
return;
|
|
|
|
REPLY_MACRO_DETAILS2_END (VL_API_LCP_DEFAULT_NS_GET_REPLY, ({
|
|
ns = (char *) lcp_get_default_ns ();
|
|
if (ns)
|
|
clib_strncpy ((char *) rmp->netns, ns,
|
|
LCP_NS_LEN - 1);
|
|
}));
|
|
}
|
|
|
|
static void
|
|
vl_api_lcp_itf_pair_replace_begin_t_handler (
|
|
vl_api_lcp_itf_pair_replace_begin_t *mp)
|
|
{
|
|
vl_api_lcp_itf_pair_replace_begin_reply_t *rmp;
|
|
int rv;
|
|
|
|
rv = lcp_itf_pair_replace_begin ();
|
|
|
|
REPLY_MACRO (VL_API_LCP_ITF_PAIR_REPLACE_BEGIN_REPLY);
|
|
}
|
|
|
|
static void
|
|
vl_api_lcp_itf_pair_replace_end_t_handler (
|
|
vl_api_lcp_itf_pair_replace_end_t *mp)
|
|
{
|
|
vl_api_lcp_itf_pair_replace_end_reply_t *rmp;
|
|
int rv = 0;
|
|
|
|
rv = lcp_itf_pair_replace_end ();
|
|
|
|
REPLY_MACRO (VL_API_LCP_ITF_PAIR_REPLACE_END_REPLY);
|
|
}
|
|
|
|
/*
|
|
* Set up the API message handling tables
|
|
*/
|
|
#include <lcpng/lcpng_if.api.c>
|
|
|
|
static clib_error_t *
|
|
lcp_plugin_api_hookup (vlib_main_t *vm)
|
|
{
|
|
/* Ask for a correctly-sized block of API message decode slots */
|
|
lcp_msg_id_base = setup_message_id_table ();
|
|
|
|
return (NULL);
|
|
}
|
|
|
|
VLIB_INIT_FUNCTION (lcp_plugin_api_hookup);
|
|
|
|
#include <vpp/app/version.h>
|
|
VLIB_PLUGIN_REGISTER () = {
|
|
.version = VPP_BUILD_VER,
|
|
.description = "Linux Control Plane - Interface Mirror",
|
|
.default_disabled = 1,
|
|
};
|
|
|
|
/*
|
|
* fd.io coding-style-patch-verification: ON
|
|
*
|
|
* Local Variables:
|
|
* eval: (c-set-style "gnu")
|
|
* End:
|
|
*/
|