zebra: Fix lsp add/del from kernel using SETFLAG

Setup a interface such that the add/del of lsp's from
the kernel can have a callback for success/failure.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2017-11-29 08:53:33 -05:00
parent 0c555cc6a5
commit 4a83e7a04a
7 changed files with 133 additions and 97 deletions

View File

@ -77,9 +77,23 @@ extern int kernel_address_delete_ipv4(struct interface *, struct connected *);
extern int kernel_neigh_update(int, int, uint32_t, char *, int);
extern int kernel_interface_set_master(struct interface *master,
struct interface *slave);
extern int kernel_add_lsp(zebra_lsp_t *);
extern int kernel_upd_lsp(zebra_lsp_t *);
extern int kernel_del_lsp(zebra_lsp_t *);
extern void kernel_add_lsp(zebra_lsp_t *lsp);
extern void kernel_upd_lsp(zebra_lsp_t *lsp);
extern void kernel_del_lsp(zebra_lsp_t *lsp);
/*
* Add the ability to pass back up the lsp install/delete
* success/failure.
*
* This functions goal is similiar to kernel_route_rib_pass_fail
* in that we are separating out the mechanics for
* the install/failure to set/unset flags and to notify
* as needed.
*/
extern void kernel_lsp_pass_fail(zebra_lsp_t *lsp,
enum southbound_results res);
extern int mpls_kernel_init(void);
extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute);

View File

@ -2432,17 +2432,6 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp)
_netlink_mpls_build_singlepath(routedesc, nhlfe,
&req.n, &req.r,
sizeof req, cmd);
if (cmd == RTM_NEWROUTE) {
SET_FLAG(nhlfe->flags,
NHLFE_FLAG_INSTALLED);
SET_FLAG(nexthop->flags,
NEXTHOP_FLAG_FIB);
} else {
UNSET_FLAG(nhlfe->flags,
NHLFE_FLAG_INSTALLED);
UNSET_FLAG(nexthop->flags,
NEXTHOP_FLAG_FIB);
}
nexthop_num++;
break;
}
@ -2486,18 +2475,6 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp)
rta, rtnh, &req.r,
&src1);
rtnh = RTNH_NEXT(rtnh);
if (cmd == RTM_NEWROUTE) {
SET_FLAG(nhlfe->flags,
NHLFE_FLAG_INSTALLED);
SET_FLAG(nexthop->flags,
NEXTHOP_FLAG_FIB);
} else {
UNSET_FLAG(nhlfe->flags,
NHLFE_FLAG_INSTALLED);
UNSET_FLAG(nexthop->flags,
NEXTHOP_FLAG_FIB);
}
}
}

View File

@ -394,7 +394,7 @@ void kernel_route_rib(struct prefix *p, struct prefix *src_p,
if (src_p && src_p->prefixlen) {
zlog_err("route add: IPv6 sourcedest routes unsupported!");
return 1;
return;
}
if (zserv_privs.change(ZPRIVS_RAISE))
@ -413,7 +413,7 @@ void kernel_route_rib(struct prefix *p, struct prefix *src_p,
kernel_route_rib_pass_fail(p, new,
(!route) ?
SOUTHBOUND_INSTALL_SUCCESS :
SOUTBHOUND_INSTALL_FAILURE);
SOUTHBOUND_INSTALL_FAILURE);
} else {
kernel_route_rib_pass_fail(p, old,
(!route) ?

View File

@ -839,18 +839,11 @@ static void lsp_select_best_nhlfe(zebra_lsp_t *lsp)
*/
static void lsp_uninstall_from_kernel(struct hash_backet *backet, void *ctxt)
{
int ret;
zebra_lsp_t *lsp;
lsp = (zebra_lsp_t *)backet->data;
if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) {
ret = kernel_del_lsp(lsp);
if (!ret) {
UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
clear_nhlfe_installed(lsp);
}
}
if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED))
kernel_del_lsp(lsp);
}
/*
@ -871,7 +864,6 @@ static void lsp_schedule(struct hash_backet *backet, void *ctxt)
*/
static wq_item_status lsp_process(struct work_queue *wq, void *data)
{
int ret = 1;
zebra_lsp_t *lsp;
zebra_nhlfe_t *oldbest, *newbest;
char buf[BUFSIZ], buf2[BUFSIZ];
@ -905,12 +897,7 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
if (newbest) {
UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED);
ret = kernel_add_lsp(lsp);
if (!ret)
SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
else
clear_nhlfe_installed(lsp);
kernel_add_lsp(lsp);
zvrf->lsp_installs++;
}
@ -918,12 +905,7 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
/* Installed, may need an update and/or delete. */
if (!newbest) {
ret = kernel_del_lsp(lsp);
if (!ret) {
UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
clear_nhlfe_installed(lsp);
}
kernel_del_lsp(lsp);
zvrf->lsp_removals++;
} else if (CHECK_FLAG(lsp->flags, LSP_FLAG_CHANGED)) {
@ -931,12 +913,7 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED);
UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
ret = kernel_upd_lsp(lsp);
if (!ret)
SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
else
clear_nhlfe_installed(lsp);
kernel_upd_lsp(lsp);
zvrf->lsp_installs++;
}
@ -1659,6 +1636,42 @@ static int mpls_processq_init(struct zebra_t *zebra)
/* Public functions */
void kernel_lsp_pass_fail(zebra_lsp_t *lsp,
enum southbound_results res)
{
struct nexthop *nexthop;
zebra_nhlfe_t *nhlfe;
if (!lsp)
return;
switch (res) {
case SOUTHBOUND_INSTALL_FAILURE:
UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
clear_nhlfe_installed(lsp);
zlog_warn("LSP Install Failure: %u", lsp->ile.in_label);
break;
case SOUTHBOUND_INSTALL_SUCCESS:
SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
nexthop = nhlfe->nexthop;
if (!nexthop)
continue;
SET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
}
break;
case SOUTHBOUND_DELETE_SUCCESS:
UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
clear_nhlfe_installed(lsp);
break;
case SOUTHBOUND_DELETE_FAILURE:
zlog_warn("LSP Deletion Failure: %u", lsp->ile.in_label);
break;
}
}
/*
* String to label conversion, labels separated by '/'.
*

View File

@ -29,16 +29,21 @@
/*
* Install Label Forwarding entry into the kernel.
*/
int kernel_add_lsp(zebra_lsp_t *lsp)
void kernel_add_lsp(zebra_lsp_t *lsp)
{
int ret;
if (!lsp || !lsp->best_nhlfe) // unexpected
return -1;
if (!lsp || !lsp->best_nhlfe) { // unexpected
kernel_lsp_pass_fail(lsp, SOUTHBOUND_INSTALL_FAILURE);
return;
}
ret = netlink_mpls_multipath(RTM_NEWROUTE, lsp);
return ret;
kernel_lsp_pass_fail(lsp,
(!ret) ?
SOUTHBOUND_INSTALL_SUCCESS :
SOUTHBOUND_INSTALL_FAILURE);
}
/*
@ -52,14 +57,16 @@ int kernel_add_lsp(zebra_lsp_t *lsp)
* through the metric field (before kernel-MPLS). This shouldn't be an issue
* any longer, so REPLACE can be reintroduced.
*/
int kernel_upd_lsp(zebra_lsp_t *lsp)
void kernel_upd_lsp(zebra_lsp_t *lsp)
{
int ret;
zebra_nhlfe_t *nhlfe;
struct nexthop *nexthop;
if (!lsp || !lsp->best_nhlfe) // unexpected
return -1;
if (!lsp || !lsp->best_nhlfe) { // unexpected
kernel_lsp_pass_fail(lsp, SOUTHBOUND_INSTALL_FAILURE);
return;
}
/* Any NHLFE that was installed but is not selected now needs to
* have its flags updated.
@ -78,25 +85,37 @@ int kernel_upd_lsp(zebra_lsp_t *lsp)
ret = netlink_mpls_multipath(RTM_NEWROUTE, lsp);
return ret;
kernel_lsp_pass_fail(lsp,
(!ret) ?
SOUTHBOUND_INSTALL_SUCCESS :
SOUTHBOUND_INSTALL_FAILURE);
}
/*
* Delete Label Forwarding entry from the kernel.
*/
int kernel_del_lsp(zebra_lsp_t *lsp)
void kernel_del_lsp(zebra_lsp_t *lsp)
{
int ret;
if (!lsp) // unexpected
return -1;
if (!lsp) { // unexpected
kernel_lsp_pass_fail(lsp,
SOUTHBOUND_DELETE_FAILURE);
return;
}
if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED))
return -1;
if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) {
kernel_lsp_pass_fail(lsp,
SOUTHBOUND_DELETE_FAILURE);
return;
}
ret = netlink_mpls_multipath(RTM_DELROUTE, lsp);
return ret;
kernel_lsp_pass_fail(lsp,
(!ret) ?
SOUTHBOUND_DELETE_SUCCESS :
SOUTHBOUND_DELETE_FAILURE);
}
int mpls_kernel_init(void)

View File

@ -24,17 +24,17 @@
#if !defined(HAVE_NETLINK) && !defined(OPEN_BSD)
int kernel_add_lsp(zebra_lsp_t *lsp)
void kernel_add_lsp(zebra_lsp_t *lsp)
{
return 0;
return;
}
int kernel_upd_lsp(zebra_lsp_t *lsp)
void kernel_upd_lsp(zebra_lsp_t *lsp)
{
return 0;
return;
}
int kernel_del_lsp(zebra_lsp_t *lsp)
void kernel_del_lsp(zebra_lsp_t *lsp)
{
return 0;
return;
}
int mpls_kernel_init(void)
{

View File

@ -279,56 +279,69 @@ static int kernel_lsp_cmd(int action, zebra_lsp_t *lsp)
default:
break;
}
if (action == RTM_ADD || action == RTM_CHANGE) {
SET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
} else {
UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
}
}
}
return (0);
}
int kernel_add_lsp(zebra_lsp_t *lsp)
void kernel_add_lsp(zebra_lsp_t *lsp)
{
int ret;
if (!lsp || !lsp->best_nhlfe) // unexpected
return -1;
if (!lsp || !lsp->best_nhlfe) { // unexpected
kernel_lsp_pass_fail(lsp, SOUTHBOUND_INSTALL_FAILURE);
return;
}
ret = kernel_lsp_cmd(RTM_ADD, lsp);
return ret;
kernel_lsp_pass_fail(lsp,
(!ret) ?
SOUTHBOUND_INSTALL_SUCCESS :
SOUTHBOUND_INSTALL_FAILURE);
}
int kernel_upd_lsp(zebra_lsp_t *lsp)
void kernel_upd_lsp(zebra_lsp_t *lsp)
{
int ret;
if (!lsp || !lsp->best_nhlfe) // unexpected
return -1;
if (!lsp || !lsp->best_nhlfe) { // unexpected
kernel_lsp_pass_fail(lsp, SOUTHBOUND_INSTALL_FAILURE);
return;
}
ret = kernel_lsp_cmd(RTM_CHANGE, lsp);
return ret;
kernel_lsp_pass_fail(lsp,
(!ret) ?
SOUTHBOUND_INSTALL_SUCCESS :
SOUTHBOUND_INSTALL_FAILURE);
return;
}
int kernel_del_lsp(zebra_lsp_t *lsp)
void kernel_del_lsp(zebra_lsp_t *lsp)
{
int ret;
if (!lsp) // unexpected
return -1;
if (!lsp) { // unexpected
kernel_lsp_pass_fail(lsp,
SOUTHBOUND_DELETE_FAILURE);
return;
}
if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED))
return -1;
if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) {
kernel_lsp_pass_fail(lsp,
SOUTHBOUND_DELETE_FAILURE);
return;
}
ret = kernel_lsp_cmd(RTM_DELETE, lsp);
return ret;
kernel_lsp_pass_fail(lsp,
(!ret) ?
SOUTHBOUND_DELETE_SUCCESS :
SOUTHBOUND_DELETE_FAILURE);
}
static int kmpw_install(struct zebra_pw *pw)