Compare commits
10 Commits
3ecbb0199e
...
6f5cde1aff
Author | SHA1 | Date | |
---|---|---|---|
6f5cde1aff | |||
61386a1c63 | |||
25b2999485 | |||
cb78074e46 | |||
0d864a71fe | |||
e19f45e29c | |||
a960d64a87 | |||
c8dc522fe9 | |||
4b9c556f08 | |||
7e482adb4f |
26
README.md
26
README.md
@ -13,28 +13,30 @@ See previous work:
|
|||||||
* [netlink listener](https://gerrit.fd.io/r/c/vpp/+/31122)
|
* [netlink listener](https://gerrit.fd.io/r/c/vpp/+/31122)
|
||||||
|
|
||||||
My work is intended to be re-submitted for review as a cleanup/rewrite of the
|
My work is intended to be re-submitted for review as a cleanup/rewrite of the
|
||||||
existing Linux CP interface mirror and netlink syncer.
|
existing Linux CP interface mirror and netlink syncer. I will use this repo
|
||||||
|
to make rapid prototyping progress, sometimes with other software engineers.
|
||||||
|
|
||||||
Follow along on [my blog](https://ipng.ch/s/articles/) for my findings while
|
Follow along on [my blog](https://ipng.ch/s/articles/) for my findings while
|
||||||
I work towards a completed plugin that can copy VPP configuration into Linux
|
I work towards feature completion. When the code is complete, this plugin should
|
||||||
interfaces, and copy Linux configuration changes into VPP (ie. a fully
|
be able to work seamlessly with a higher level controlplane like [FRR](https://frrouting.org/)
|
||||||
bidirectional pipe between Linux and VPP).
|
or [Bird](https://bird.network.cz/), for example as a BGP/OSPF speaking ISP router.
|
||||||
|
|
||||||
When the code is complete, this plugin should be able to work seamlessly with
|
|
||||||
a higher level controlplane like [FRR](https://frrouting.org/) or
|
|
||||||
[Bird](https://bird.network.cz/), for example as a BGP/OSPF speaking ISP router.
|
|
||||||
|
|
||||||
## WARNING!!
|
## WARNING!!
|
||||||
|
|
||||||
The only reason that this code is here, is so that I can make some progress
|
Users should use the `linux-cp` plugin that natively ships with VPP since 2022.
|
||||||
|
|
||||||
|
The only reason that this code is still here, is so that I can make some progress
|
||||||
iterating on the Linux CP plugin, and share my findings with some interested
|
iterating on the Linux CP plugin, and share my findings with some interested
|
||||||
folks. The goal is NOT to use this plugin anywhere other than a bench. I
|
folks. The goal is NOT to use this plugin anywhere other than a bench. I
|
||||||
intend to contribute the plugin back upstream as soon as it's peer reviewed!
|
intend to contribute any changes submitted to this copy of the plugin back
|
||||||
|
upstream as soon as they have had some mileage and peer review!
|
||||||
|
|
||||||
***Pull Requests and Issues will be immediately closed without warning***
|
***Pull Requests and Issues will be immediately closed without warning***
|
||||||
|
|
||||||
VPP's code lives at [fd.io](https://gerrit.fd.io/r/c/vpp), and this copy is
|
VPP's code lives at [fd.io](https://gerrit.fd.io/r/c/vpp), and this copy is
|
||||||
shared only for convenience purposes.
|
shared only for convenience purposes. If you do require support, you can
|
||||||
|
discuss your case on the VPP Developer mailinglist at vpp-dev@lists.fd.io
|
||||||
|
or alternatively you can ask for a commercial support quote at sales@ipng.ch.
|
||||||
|
|
||||||
## Functionality
|
## Functionality
|
||||||
|
|
||||||
@ -158,7 +160,7 @@ wget http://deb.debian.org/debian/pool/main/libn/libnl3/libnl3_3.7.0-0.2.debian.
|
|||||||
|
|
||||||
tar xzf libnl3_3.7.0.orig.tar.gz
|
tar xzf libnl3_3.7.0.orig.tar.gz
|
||||||
cd libnl-3.7.0
|
cd libnl-3.7.0
|
||||||
tar xf libnl3_3.7.0-0.2.debian.tar.xz
|
tar xf ../libnl3_3.7.0-0.2.debian.tar.xz
|
||||||
|
|
||||||
sudo apt install dpkg-dev debhelper dh-exec cdbs bison flex automake autoconf \
|
sudo apt install dpkg-dev debhelper dh-exec cdbs bison flex automake autoconf \
|
||||||
dh-autoreconf pkg-config
|
dh-autoreconf pkg-config
|
||||||
|
42
lcpng.c
42
lcpng.c
@ -95,6 +95,26 @@ lcp_sync (void)
|
|||||||
return lcpm->lcp_sync;
|
return lcpm->lcp_sync;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
lcp_set_sync_unnumbered (u8 is_sync)
|
||||||
|
{
|
||||||
|
lcp_main_t *lcpm = &lcp_main;
|
||||||
|
|
||||||
|
lcpm->lcp_sync_unnumbered = (is_sync != 0);
|
||||||
|
|
||||||
|
// If we set to 'on', do a one-off sync of LCP interfaces
|
||||||
|
if (is_sync)
|
||||||
|
lcp_itf_pair_sync_state_all ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lcp_sync_unnumbered (void)
|
||||||
|
{
|
||||||
|
lcp_main_t *lcpm = &lcp_main;
|
||||||
|
|
||||||
|
return lcpm->lcp_sync_unnumbered;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
lcp_set_auto_subint (u8 is_auto)
|
lcp_set_auto_subint (u8 is_auto)
|
||||||
{
|
{
|
||||||
@ -111,6 +131,28 @@ lcp_auto_subint (void)
|
|||||||
return lcpm->lcp_auto_subint;
|
return lcpm->lcp_auto_subint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
lcp_set_default_num_queues (u16 num_queues, u8 is_tx)
|
||||||
|
{
|
||||||
|
lcp_main_t *lcpm = &lcp_main;
|
||||||
|
|
||||||
|
if (is_tx)
|
||||||
|
lcpm->num_tx_queues = num_queues;
|
||||||
|
else
|
||||||
|
lcpm->num_rx_queues = num_queues;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16
|
||||||
|
lcp_get_default_num_queues (u8 is_tx)
|
||||||
|
{
|
||||||
|
lcp_main_t *lcpm = &lcp_main;
|
||||||
|
|
||||||
|
if (is_tx)
|
||||||
|
return lcpm->num_tx_queues;
|
||||||
|
|
||||||
|
return lcpm->num_rx_queues ?: vlib_num_workers ();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fd.io coding-style-patch-verification: ON
|
* fd.io coding-style-patch-verification: ON
|
||||||
*
|
*
|
||||||
|
11
lcpng.h
11
lcpng.h
@ -26,6 +26,9 @@ typedef struct lcp_main_s
|
|||||||
int default_ns_fd;
|
int default_ns_fd;
|
||||||
u8 lcp_auto_subint; /* Automatically create/delete LCP sub-interfaces */
|
u8 lcp_auto_subint; /* Automatically create/delete LCP sub-interfaces */
|
||||||
u8 lcp_sync; /* Automatically sync VPP changes to LCP */
|
u8 lcp_sync; /* Automatically sync VPP changes to LCP */
|
||||||
|
u8 lcp_sync_unnumbered; /* Automatically sync unnumbered interfaces to LCP */
|
||||||
|
u16 num_rx_queues;
|
||||||
|
u16 num_tx_queues;
|
||||||
/* Set when Unit testing */
|
/* Set when Unit testing */
|
||||||
u8 test_mode;
|
u8 test_mode;
|
||||||
} lcp_main_t;
|
} lcp_main_t;
|
||||||
@ -39,11 +42,17 @@ int lcp_set_default_ns (u8 *ns);
|
|||||||
u8 *lcp_get_default_ns (void); /* Returns NULL or shared string */
|
u8 *lcp_get_default_ns (void); /* Returns NULL or shared string */
|
||||||
int lcp_get_default_ns_fd (void);
|
int lcp_get_default_ns_fd (void);
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Sync state from VPP into all LCP devices
|
* Sync state from VPP into all LCP devices
|
||||||
*/
|
*/
|
||||||
void lcp_itf_pair_sync_state_all ();
|
void lcp_itf_pair_sync_state_all ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get/Set the default queue number for LCP host taps.
|
||||||
|
*/
|
||||||
|
void lcp_set_default_num_queues (u16 num_queues, u8 is_tx);
|
||||||
|
u16 lcp_get_default_num_queues (u8 is_tx);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
19
lcpng_if.api
19
lcpng_if.api
@ -101,13 +101,28 @@ define lcp_itf_pair_add_del_v2_reply
|
|||||||
@param context - sender context, to match reply w/ request
|
@param context - sender context, to match reply w/ request
|
||||||
@param sw_if_index - interface to use as filter (~0 == "all")
|
@param sw_if_index - interface to use as filter (~0 == "all")
|
||||||
*/
|
*/
|
||||||
define lcp_itf_pair_get
|
autoendian define lcp_itf_pair_get
|
||||||
{
|
{
|
||||||
u32 client_index;
|
u32 client_index;
|
||||||
u32 context;
|
u32 context;
|
||||||
u32 cursor;
|
u32 cursor;
|
||||||
};
|
};
|
||||||
define lcp_itf_pair_get_reply
|
autoendian define lcp_itf_pair_get_reply
|
||||||
|
{
|
||||||
|
u32 context;
|
||||||
|
i32 retval;
|
||||||
|
u32 cursor;
|
||||||
|
};
|
||||||
|
|
||||||
|
autoendian define lcp_itf_pair_get_v2
|
||||||
|
{
|
||||||
|
u32 client_index;
|
||||||
|
u32 context;
|
||||||
|
u32 cursor;
|
||||||
|
vl_api_interface_index_t sw_if_index [default=0xffffffff];
|
||||||
|
};
|
||||||
|
|
||||||
|
autoendian define lcp_itf_pair_get_v2_reply
|
||||||
{
|
{
|
||||||
u32 context;
|
u32 context;
|
||||||
i32 retval;
|
i32 retval;
|
||||||
|
@ -133,11 +133,11 @@ send_lcp_itf_pair_details (index_t lipi, vl_api_registration_t *rp,
|
|||||||
vl_api_lcp_itf_pair_details_t *rmp;
|
vl_api_lcp_itf_pair_details_t *rmp;
|
||||||
lcp_itf_pair_t *lcp_pair = lcp_itf_pair_get (lipi);
|
lcp_itf_pair_t *lcp_pair = lcp_itf_pair_get (lipi);
|
||||||
|
|
||||||
REPLY_MACRO_DETAILS4 (
|
REPLY_MACRO_DETAILS4_END (
|
||||||
VL_API_LCP_ITF_PAIR_DETAILS, rp, context, ({
|
VL_API_LCP_ITF_PAIR_DETAILS, rp, context, ({
|
||||||
rmp->phy_sw_if_index = ntohl (lcp_pair->lip_phy_sw_if_index);
|
rmp->phy_sw_if_index = lcp_pair->lip_phy_sw_if_index;
|
||||||
rmp->host_sw_if_index = ntohl (lcp_pair->lip_host_sw_if_index);
|
rmp->host_sw_if_index = lcp_pair->lip_host_sw_if_index;
|
||||||
rmp->vif_index = ntohl (lcp_pair->lip_vif_index);
|
rmp->vif_index = lcp_pair->lip_vif_index;
|
||||||
rmp->host_if_type = api_encode_host_type (lcp_pair->lip_host_type);
|
rmp->host_if_type = api_encode_host_type (lcp_pair->lip_host_type);
|
||||||
|
|
||||||
memcpy_s (rmp->host_if_name, sizeof (rmp->host_if_name),
|
memcpy_s (rmp->host_if_name, sizeof (rmp->host_if_name),
|
||||||
@ -156,11 +156,44 @@ 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;
|
vl_api_lcp_itf_pair_get_reply_t *rmp;
|
||||||
i32 rv = 0;
|
i32 rv = 0;
|
||||||
|
|
||||||
REPLY_AND_DETAILS_MACRO (
|
REPLY_AND_DETAILS_MACRO_END (
|
||||||
VL_API_LCP_ITF_PAIR_GET_REPLY, lcp_itf_pair_pool,
|
VL_API_LCP_ITF_PAIR_GET_REPLY, lcp_itf_pair_pool,
|
||||||
({ send_lcp_itf_pair_details (cursor, rp, mp->context); }));
|
({ 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
|
static void
|
||||||
vl_api_lcp_default_ns_set_t_handler (vl_api_lcp_default_ns_set_t *mp)
|
vl_api_lcp_default_ns_set_t_handler (vl_api_lcp_default_ns_set_t *mp)
|
||||||
{
|
{
|
||||||
|
@ -142,6 +142,37 @@ VLIB_CLI_COMMAND (lcp_sync_command, static) = {
|
|||||||
.function = lcp_sync_command_fn,
|
.function = lcp_sync_command_fn,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static clib_error_t *
|
||||||
|
lcp_sync_unnumbered_command_fn (vlib_main_t *vm, unformat_input_t *input,
|
||||||
|
vlib_cli_command_t *cmd)
|
||||||
|
{
|
||||||
|
unformat_input_t _line_input, *line_input = &_line_input;
|
||||||
|
|
||||||
|
if (!unformat_user (input, unformat_line_input, line_input))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
|
||||||
|
{
|
||||||
|
if (unformat (line_input, "on") || unformat (line_input, "enable"))
|
||||||
|
lcp_set_sync_unnumbered (1);
|
||||||
|
else if (unformat (line_input, "off") ||
|
||||||
|
unformat (line_input, "disable"))
|
||||||
|
lcp_set_sync_unnumbered (0);
|
||||||
|
else
|
||||||
|
return clib_error_return (0, "unknown input `%U'",
|
||||||
|
format_unformat_error, line_input);
|
||||||
|
}
|
||||||
|
|
||||||
|
unformat_free (line_input);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
VLIB_CLI_COMMAND (lcp_sync_unnumbered_command, static) = {
|
||||||
|
.path = "lcp lcp-sync-unnumbered",
|
||||||
|
.short_help = "lcp lcp-sync-unnumbered [on|enable|off|disable]",
|
||||||
|
.function = lcp_sync_unnumbered_command_fn,
|
||||||
|
};
|
||||||
|
|
||||||
static clib_error_t *
|
static clib_error_t *
|
||||||
lcp_auto_subint_command_fn (vlib_main_t *vm, unformat_input_t *input,
|
lcp_auto_subint_command_fn (vlib_main_t *vm, unformat_input_t *input,
|
||||||
vlib_cli_command_t *cmd)
|
vlib_cli_command_t *cmd)
|
||||||
|
@ -109,7 +109,22 @@ lcp_itf_pair_sync_state (lcp_itf_pair_t *lip)
|
|||||||
/* Linux will remove IPv6 addresses on children when the parent state
|
/* Linux will remove IPv6 addresses on children when the parent state
|
||||||
* goes down, so we ensure all IPv4/IPv6 addresses are synced.
|
* goes down, so we ensure all IPv4/IPv6 addresses are synced.
|
||||||
*/
|
*/
|
||||||
|
if (sw->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
|
||||||
|
{
|
||||||
|
if (lcp_sync_unnumbered ())
|
||||||
|
{
|
||||||
lcp_itf_set_interface_addr (lip);
|
lcp_itf_set_interface_addr (lip);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LCP_IF_NOTICE ("sync_state: not syncing addresses on unnumbered %U",
|
||||||
|
format_lcp_itf_pair, lip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lcp_itf_set_interface_addr (lip);
|
||||||
|
}
|
||||||
|
|
||||||
if (vif_ns_fd != -1)
|
if (vif_ns_fd != -1)
|
||||||
close (vif_ns_fd);
|
close (vif_ns_fd);
|
||||||
|
@ -133,6 +133,8 @@ lcp_itf_pair_show (u32 phy_sw_if_index)
|
|||||||
vlib_cli_output (vm, "lcp lcp-auto-subint %s\n",
|
vlib_cli_output (vm, "lcp lcp-auto-subint %s\n",
|
||||||
lcp_auto_subint () ? "on" : "off");
|
lcp_auto_subint () ? "on" : "off");
|
||||||
vlib_cli_output (vm, "lcp lcp-sync %s\n", lcp_sync () ? "on" : "off");
|
vlib_cli_output (vm, "lcp lcp-sync %s\n", lcp_sync () ? "on" : "off");
|
||||||
|
vlib_cli_output (vm, "lcp lcp-sync-unnumbered %s\n",
|
||||||
|
lcp_sync_unnumbered () ? "on" : "off");
|
||||||
|
|
||||||
if (phy_sw_if_index == ~0)
|
if (phy_sw_if_index == ~0)
|
||||||
{
|
{
|
||||||
@ -261,7 +263,10 @@ lcp_itf_pair_add (u32 host_sw_if_index, u32 phy_sw_if_index, u8 *host_name,
|
|||||||
vec_validate_init_empty (lip_db_by_host, host_sw_if_index, INDEX_INVALID);
|
vec_validate_init_empty (lip_db_by_host, host_sw_if_index, INDEX_INVALID);
|
||||||
lip_db_by_phy[phy_sw_if_index] = lipi;
|
lip_db_by_phy[phy_sw_if_index] = lipi;
|
||||||
lip_db_by_host[host_sw_if_index] = lipi;
|
lip_db_by_host[host_sw_if_index] = lipi;
|
||||||
|
if (clib_strcmp ((char *) ns, (char *) lcp_get_default_ns ()) == 0)
|
||||||
|
{
|
||||||
hash_set (lip_db_by_vif, host_index, lipi);
|
hash_set (lip_db_by_vif, host_index, lipi);
|
||||||
|
}
|
||||||
|
|
||||||
lip->lip_host_sw_if_index = host_sw_if_index;
|
lip->lip_host_sw_if_index = host_sw_if_index;
|
||||||
lip->lip_phy_sw_if_index = phy_sw_if_index;
|
lip->lip_phy_sw_if_index = phy_sw_if_index;
|
||||||
@ -550,6 +555,7 @@ 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 *default_ns;
|
u8 *default_ns;
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
default_ns = NULL;
|
default_ns = NULL;
|
||||||
|
|
||||||
@ -569,6 +575,10 @@ lcp_itf_pair_config (vlib_main_t *vm, unformat_input_t *input)
|
|||||||
lcp_set_auto_subint (1 /* is_auto */);
|
lcp_set_auto_subint (1 /* is_auto */);
|
||||||
else if (unformat (input, "lcp-sync"))
|
else if (unformat (input, "lcp-sync"))
|
||||||
lcp_set_sync (1 /* is_auto */);
|
lcp_set_sync (1 /* is_auto */);
|
||||||
|
else if (unformat (input, "num-rx-queues %d", &tmp))
|
||||||
|
lcp_set_default_num_queues (tmp, 0 /* is_tx */);
|
||||||
|
else if (unformat (input, "num-tx-queues %d", &tmp))
|
||||||
|
lcp_set_default_num_queues (tmp, 1 /* is_tx */);
|
||||||
else
|
else
|
||||||
return clib_error_return (0, "unknown input `%U'",
|
return clib_error_return (0, "unknown input `%U'",
|
||||||
format_unformat_error, input);
|
format_unformat_error, input);
|
||||||
@ -782,6 +792,14 @@ lcp_itf_pair_create (u32 phy_sw_if_index, u8 *host_if_name,
|
|||||||
const vnet_sw_interface_t *sw;
|
const vnet_sw_interface_t *sw;
|
||||||
const vnet_hw_interface_t *hw;
|
const vnet_hw_interface_t *hw;
|
||||||
lcp_itf_pair_t *lip;
|
lcp_itf_pair_t *lip;
|
||||||
|
index_t lipi;
|
||||||
|
|
||||||
|
lipi = lcp_itf_pair_find_by_phy (phy_sw_if_index);
|
||||||
|
if (lipi != INDEX_INVALID)
|
||||||
|
{
|
||||||
|
LCP_IF_ERROR ("pair_create: already created");
|
||||||
|
return VNET_API_ERROR_VALUE_EXIST;
|
||||||
|
}
|
||||||
|
|
||||||
if (!vnet_sw_if_index_is_api_valid (phy_sw_if_index))
|
if (!vnet_sw_if_index_is_api_valid (phy_sw_if_index))
|
||||||
{
|
{
|
||||||
@ -983,8 +1001,10 @@ lcp_itf_pair_create (u32 phy_sw_if_index, u8 *host_if_name,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
tap_create_if_args_t args = {
|
tap_create_if_args_t args = {
|
||||||
.num_rx_queues = clib_max (1, vlib_num_workers ()),
|
.num_rx_queues =
|
||||||
.num_tx_queues = 1,
|
clib_max (1, lcp_get_default_num_queues (0 /* is_tx */)),
|
||||||
|
.num_tx_queues =
|
||||||
|
clib_max (1, lcp_get_default_num_queues (1 /* is_tx */)),
|
||||||
.id = ~0,
|
.id = ~0,
|
||||||
.sw_if_index = ~0,
|
.sw_if_index = ~0,
|
||||||
.rx_ring_sz = 256,
|
.rx_ring_sz = 256,
|
||||||
@ -1078,7 +1098,7 @@ lcp_itf_pair_create (u32 phy_sw_if_index, u8 *host_if_name,
|
|||||||
vnet_sw_interface_admin_up (vnm, host_sw_if_index);
|
vnet_sw_interface_admin_up (vnm, host_sw_if_index);
|
||||||
if (lcp_sync ())
|
if (lcp_sync ())
|
||||||
{
|
{
|
||||||
lip = lcp_itf_pair_get (lcp_itf_pair_find_by_vif (vif_index));
|
lip = lcp_itf_pair_get (lcp_itf_pair_find_by_phy (phy_sw_if_index));
|
||||||
lcp_itf_pair_sync_state (lip);
|
lcp_itf_pair_sync_state (lip);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -1225,6 +1245,8 @@ lcp_itf_pair_init (vlib_main_t *vm)
|
|||||||
tcp_punt_unknown (vm, 0, 1);
|
tcp_punt_unknown (vm, 0, 1);
|
||||||
tcp_punt_unknown (vm, 1, 1);
|
tcp_punt_unknown (vm, 1, 1);
|
||||||
|
|
||||||
|
lcp_main.lcp_sync_unnumbered = 1;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,6 +166,12 @@ int lcp_auto_subint (void);
|
|||||||
void lcp_set_sync (u8 is_auto);
|
void lcp_set_sync (u8 is_auto);
|
||||||
int lcp_sync (void);
|
int lcp_sync (void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sync address of unnumbered interfaces from VPP into LCP
|
||||||
|
*/
|
||||||
|
void lcp_set_sync_unnumbered (u8 is_sync);
|
||||||
|
int lcp_sync_unnumbered (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 *);
|
||||||
|
|
||||||
|
@ -1149,7 +1149,7 @@ lcp_nl_neigh_add (struct rtnl_neigh *rn)
|
|||||||
|
|
||||||
if ((rna = rtnl_neigh_get_dst (rn)) == NULL)
|
if ((rna = rtnl_neigh_get_dst (rn)) == NULL)
|
||||||
{
|
{
|
||||||
LCP_NL_DBG ("neigh_del: ignore missing neighbor %U", format_nl_object,
|
LCP_NL_DBG ("neigh_add: ignore missing neighbor %U", format_nl_object,
|
||||||
rn);
|
rn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user