Add automatic LCP creation
Update the pair_config() parser to follow suite. When the configuration 'lcp-auto-subint' is set, and the interface at hand is a subinterface, in lcp_itf_interface_add_del(): - if it's a deletion and we're a sub-int, and we have a LIP: delete it. - if it's a creation and we're a sub-int, and our parent has a LIP, create one. Fix a few logging consistency issues (pair_del), and in pair_delete_by_index() ensure that the right namespace is selected. Due to this quirk with lip->lip_namespace not wanting to be a vec_dup() string, rewrite them all to be strdup/free instead.
This commit is contained in:
16
lcpng.c
16
lcpng.c
@ -69,6 +69,22 @@ int lcp_set_default_ns(u8 *ns) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
lcp_set_auto_subint (u8 is_auto)
|
||||||
|
{
|
||||||
|
lcp_main_t *lcpm = &lcp_main;
|
||||||
|
|
||||||
|
lcpm->auto_subint = (is_auto != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lcp_auto_subint (void)
|
||||||
|
{
|
||||||
|
lcp_main_t *lcpm = &lcp_main;
|
||||||
|
|
||||||
|
return lcpm->auto_subint;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fd.io coding-style-patch-verification: ON
|
* fd.io coding-style-patch-verification: ON
|
||||||
*
|
*
|
||||||
|
1
lcpng.h
1
lcpng.h
@ -24,6 +24,7 @@ typedef struct lcp_main_s
|
|||||||
u16 msg_id_base; /* API message ID base */
|
u16 msg_id_base; /* API message ID base */
|
||||||
u8 default_namespace[LCP_NS_LEN]; /* default namespace if set */
|
u8 default_namespace[LCP_NS_LEN]; /* default namespace if set */
|
||||||
int default_ns_fd;
|
int default_ns_fd;
|
||||||
|
u8 auto_subint; /* Automatically create/delete LCP sub-interfaces */
|
||||||
/* Set when Unit testing */
|
/* Set when Unit testing */
|
||||||
u8 test_mode;
|
u8 test_mode;
|
||||||
} lcp_main_t;
|
} lcp_main_t;
|
||||||
|
@ -452,14 +452,16 @@ static clib_error_t *
|
|||||||
lcp_itf_interface_add_del (vnet_main_t *vnm, u32 sw_if_index, u32 is_create)
|
lcp_itf_interface_add_del (vnet_main_t *vnm, u32 sw_if_index, u32 is_create)
|
||||||
{
|
{
|
||||||
const vnet_sw_interface_t *sw;
|
const vnet_sw_interface_t *sw;
|
||||||
const lcp_itf_pair_t *sup_lip;
|
|
||||||
uword is_sub;
|
uword is_sub;
|
||||||
|
|
||||||
is_sub = vnet_sw_interface_is_sub (vnm, sw_if_index);
|
is_sub = vnet_sw_interface_is_sub (vnm, sw_if_index);
|
||||||
LCP_ITF_PAIR_DBG ("interface_%s: [%u] sw %U is_sub %u",
|
LCP_ITF_PAIR_DBG ("interface_%s: [%u] sw %U is_sub %u auto-subint %u",
|
||||||
is_create ? "add" : "del", sw_if_index,
|
is_create ? "add" : "del", sw_if_index,
|
||||||
format_vnet_sw_if_index_name, vnet_get_main (),
|
format_vnet_sw_if_index_name, vnet_get_main (),
|
||||||
sw_if_index, is_sub);
|
sw_if_index, is_sub, lcp_auto_subint ());
|
||||||
|
|
||||||
|
if (!lcp_auto_subint ())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
sw = vnet_get_sw_interface_or_null (vnm, sw_if_index);
|
sw = vnet_get_sw_interface_or_null (vnm, sw_if_index);
|
||||||
if (!sw)
|
if (!sw)
|
||||||
@ -472,21 +474,39 @@ lcp_itf_interface_add_del (vnet_main_t *vnm, u32 sw_if_index, u32 is_create)
|
|||||||
sw->sw_if_index, format_vnet_sw_if_index_name,
|
sw->sw_if_index, format_vnet_sw_if_index_name,
|
||||||
vnet_get_main (), sw->sup_sw_if_index);
|
vnet_get_main (), sw->sup_sw_if_index);
|
||||||
|
|
||||||
// If the parent has a LIP and we're in auto-create, create a LIP for this
|
if (is_create)
|
||||||
// child
|
{
|
||||||
sup_lip = lcp_itf_pair_get (lcp_itf_pair_find_by_phy (sw->sup_sw_if_index));
|
const lcp_itf_pair_t *sup_lip;
|
||||||
if (!sup_lip)
|
u8 *name = 0;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
LCP_ITF_PAIR_INFO (
|
// If the parent has a LIP auto-create a LIP for this interface
|
||||||
"interface_%s: %U has parent %U, enqueueing creation of LCP",
|
sup_lip =
|
||||||
is_create ? "add" : "del", format_vnet_sw_if_index_name, vnet_get_main (),
|
lcp_itf_pair_get (lcp_itf_pair_find_by_phy (sw->sup_sw_if_index));
|
||||||
sw->sw_if_index, format_lcp_itf_pair, sup_lip);
|
if (!sup_lip)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// We cannot create the interface here, because the previous interface for
|
name = format (name, "%s.%d", sup_lip->lip_host_name, sw->sub.id);
|
||||||
// which this is a callback hasn't returned yet.
|
|
||||||
// lcp_itf_pair_create(sw->sw_if_index, (u8 *)"foo", LCP_ITF_HOST_TAP,
|
LCP_ITF_PAIR_INFO (
|
||||||
// sup_lip->lip_namespace, NULL);
|
"interface_%s: %U has parent %U, auto-creating LCP with host-if %s",
|
||||||
|
is_create ? "add" : "del", format_vnet_sw_if_index_name,
|
||||||
|
vnet_get_main (), sw->sw_if_index, format_lcp_itf_pair, sup_lip, name);
|
||||||
|
|
||||||
|
lcp_itf_pair_create (sw->sw_if_index, name, LCP_ITF_HOST_TAP,
|
||||||
|
sup_lip->lip_namespace, NULL);
|
||||||
|
|
||||||
|
vec_free (name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const lcp_itf_pair_t *lip;
|
||||||
|
|
||||||
|
// If the interface has a LIP, auto-delete it
|
||||||
|
lip = lcp_itf_pair_get (lcp_itf_pair_find_by_phy (sw_if_index));
|
||||||
|
if (!lip)
|
||||||
|
return NULL;
|
||||||
|
lcp_itf_pair_delete (sw_if_index);
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -420,10 +420,11 @@ lcp_itf_pair_del (u32 phy_sw_if_index)
|
|||||||
|
|
||||||
lip = lcp_itf_pair_get (lipi);
|
lip = lcp_itf_pair_get (lipi);
|
||||||
|
|
||||||
LCP_ITF_PAIR_INFO ("pair delete: {%U, %U, %s}", format_vnet_sw_if_index_name,
|
LCP_ITF_PAIR_INFO (
|
||||||
vnet_get_main (), lip->lip_phy_sw_if_index,
|
"pair_del: host:%U phy:%U host_if:%s vif:%d ns:%s",
|
||||||
format_vnet_sw_if_index_name, vnet_get_main (),
|
format_vnet_sw_if_index_name, vnet_get_main (), lip->lip_host_sw_if_index,
|
||||||
lip->lip_host_sw_if_index, lip->lip_host_name);
|
format_vnet_sw_if_index_name, vnet_get_main (), lip->lip_phy_sw_if_index,
|
||||||
|
lip->lip_host_name, lip->lip_vif_index, lip->lip_namespace);
|
||||||
|
|
||||||
/* invoke registered callbacks for pair deletion */
|
/* invoke registered callbacks for pair deletion */
|
||||||
vec_foreach (vft, lcp_itf_vfts)
|
vec_foreach (vft, lcp_itf_vfts)
|
||||||
@ -463,7 +464,8 @@ lcp_itf_pair_del (u32 phy_sw_if_index)
|
|||||||
hash_unset (lip_db_by_vif, lip->lip_vif_index);
|
hash_unset (lip_db_by_vif, lip->lip_vif_index);
|
||||||
|
|
||||||
vec_free (lip->lip_host_name);
|
vec_free (lip->lip_host_name);
|
||||||
vec_free (lip->lip_namespace);
|
if (lip->lip_namespace)
|
||||||
|
free (lip->lip_namespace);
|
||||||
pool_put (lcp_itf_pair_pool, lip);
|
pool_put (lcp_itf_pair_pool, lip);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -474,24 +476,46 @@ lcp_itf_pair_delete_by_index (index_t lipi)
|
|||||||
{
|
{
|
||||||
u32 host_sw_if_index;
|
u32 host_sw_if_index;
|
||||||
lcp_itf_pair_t *lip;
|
lcp_itf_pair_t *lip;
|
||||||
u8 *host_name;
|
u8 *host_name = 0;
|
||||||
|
char *ns = 0;
|
||||||
|
|
||||||
lip = lcp_itf_pair_get (lipi);
|
lip = lcp_itf_pair_get (lipi);
|
||||||
|
|
||||||
host_name = vec_dup (lip->lip_host_name);
|
host_name = vec_dup (lip->lip_host_name);
|
||||||
|
ns = strdup ((const char *) lip->lip_namespace);
|
||||||
host_sw_if_index = lip->lip_host_sw_if_index;
|
host_sw_if_index = lip->lip_host_sw_if_index;
|
||||||
|
|
||||||
lcp_itf_pair_del (lip->lip_phy_sw_if_index);
|
lcp_itf_pair_del (lip->lip_phy_sw_if_index);
|
||||||
|
|
||||||
if (vnet_sw_interface_is_sub (vnet_get_main (), host_sw_if_index))
|
if (vnet_sw_interface_is_sub (vnet_get_main (), host_sw_if_index))
|
||||||
{
|
{
|
||||||
|
int curr_ns_fd = -1;
|
||||||
|
int vif_ns_fd = -1;
|
||||||
|
if (ns)
|
||||||
|
{
|
||||||
|
curr_ns_fd = clib_netns_open (NULL /* self */);
|
||||||
|
vif_ns_fd = clib_netns_open ((u8 *) ns);
|
||||||
|
if (vif_ns_fd != -1)
|
||||||
|
clib_setns (vif_ns_fd);
|
||||||
|
}
|
||||||
|
|
||||||
lcp_netlink_del_link ((const char *) host_name);
|
lcp_netlink_del_link ((const char *) host_name);
|
||||||
|
if (vif_ns_fd != -1)
|
||||||
|
close (vif_ns_fd);
|
||||||
|
|
||||||
|
if (curr_ns_fd != -1)
|
||||||
|
{
|
||||||
|
clib_setns (curr_ns_fd);
|
||||||
|
close (curr_ns_fd);
|
||||||
|
}
|
||||||
|
|
||||||
vnet_delete_sub_interface (host_sw_if_index);
|
vnet_delete_sub_interface (host_sw_if_index);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tap_delete_if (vlib_get_main (), host_sw_if_index);
|
tap_delete_if (vlib_get_main (), host_sw_if_index);
|
||||||
|
|
||||||
vec_free (host_name);
|
vec_free (host_name);
|
||||||
|
free (ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -524,29 +548,30 @@ lcp_itf_pair_walk (lcp_itf_pair_walk_cb_t cb, void *ctx)
|
|||||||
static clib_error_t *
|
static clib_error_t *
|
||||||
lcp_itf_pair_config (vlib_main_t *vm, unformat_input_t *input)
|
lcp_itf_pair_config (vlib_main_t *vm, unformat_input_t *input)
|
||||||
{
|
{
|
||||||
u8 *phy;
|
u8 *default_ns;
|
||||||
u8 *ns;
|
|
||||||
u8 *netns;
|
|
||||||
|
|
||||||
phy = ns = netns = NULL;
|
default_ns = NULL;
|
||||||
|
|
||||||
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
|
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
|
||||||
{
|
{
|
||||||
if (unformat (input, "netns %v", &netns))
|
if (unformat (input, "default netns %v", &default_ns))
|
||||||
{
|
{
|
||||||
vec_add1 (netns, 0);
|
vec_add1 (default_ns, 0);
|
||||||
if (lcp_set_default_ns(netns) < 0) {
|
if (lcp_set_default_ns (default_ns) < 0)
|
||||||
return clib_error_return(
|
{
|
||||||
0, "lcpng namespace must be less than %d characters",
|
return clib_error_return (
|
||||||
LCP_NS_LEN);
|
0, "linux-cp namespace must be less than %d characters",
|
||||||
}
|
LCP_NS_LEN);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (unformat (input, "lcp-auto-subint"))
|
||||||
|
lcp_set_auto_subint (1 /* is_auto */);
|
||||||
else
|
else
|
||||||
return clib_error_return (0, "interfaces not found");
|
return clib_error_return (0, "unknown input `%U'",
|
||||||
|
format_unformat_error, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec_free (phy);
|
vec_free (default_ns);
|
||||||
vec_free (netns);
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -164,6 +164,12 @@ lcp_itf_pair_find_by_host (u32 host_sw_if_index)
|
|||||||
return (lip_db_by_host[host_sw_if_index]);
|
return (lip_db_by_host[host_sw_if_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sub-interface auto creation/deletion for LCP
|
||||||
|
*/
|
||||||
|
void lcp_set_auto_subint (u8 is_auto);
|
||||||
|
int lcp_auto_subint (void);
|
||||||
|
|
||||||
typedef void (*lcp_itf_pair_add_cb_t) (lcp_itf_pair_t *);
|
typedef void (*lcp_itf_pair_add_cb_t) (lcp_itf_pair_t *);
|
||||||
typedef void (*lcp_itf_pair_del_cb_t) (lcp_itf_pair_t *);
|
typedef void (*lcp_itf_pair_del_cb_t) (lcp_itf_pair_t *);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user