Merge pull request #1496 from donaldsharp/install_failure

Additional Southbound API changes
This commit is contained in:
Renato Westphal 2017-12-04 18:25:16 -02:00 committed by GitHub
commit 50a0033c24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 290 additions and 191 deletions

View File

@ -285,9 +285,9 @@ extern int zebra_check_addr(struct prefix *p);
extern void rib_addnode(struct route_node *rn, struct route_entry *re, extern void rib_addnode(struct route_node *rn, struct route_entry *re,
int process); int process);
extern void rib_delnode(struct route_node *rn, struct route_entry *re); extern void rib_delnode(struct route_node *rn, struct route_entry *re);
extern int rib_install_kernel(struct route_node *rn, struct route_entry *re, extern void rib_install_kernel(struct route_node *rn, struct route_entry *re,
struct route_entry *old); struct route_entry *old);
extern int rib_uninstall_kernel(struct route_node *rn, struct route_entry *re); extern void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re);
/* NOTE: /* NOTE:
* All rib_add function will not just add prefix into RIB, but * All rib_add function will not just add prefix into RIB, but

View File

@ -41,17 +41,59 @@
* success failure should be handled by the caller. * success failure should be handled by the caller.
*/ */
extern int kernel_route_rib(struct prefix *, struct prefix *,
struct route_entry *, struct route_entry *); enum southbound_results {
SOUTHBOUND_INSTALL_SUCCESS,
SOUTHBOUND_INSTALL_FAILURE,
SOUTHBOUND_DELETE_SUCCESS,
SOUTHBOUND_DELETE_FAILURE,
};
/*
* Install/delete the specified prefix p from the kernel
*
* old = NULL, new = pointer - Install new
* old = pointer, new = pointer - Route replace Old w/ New
* old = pointer, new = NULL, - Route Delete
*
* Please note not all kernels support route replace
* semantics so we will end up with a delete than
* a re-add.
*/
extern void kernel_route_rib(struct prefix *p, struct prefix *src_p,
struct route_entry *old, struct route_entry *new);
/*
* So route install/failure may not be immediately known
* so let's separate it out and allow the result to
* be passed back up.
*/
extern void kernel_route_rib_pass_fail(struct prefix *p,
struct route_entry *re,
enum southbound_results res);
extern int kernel_address_add_ipv4(struct interface *, struct connected *); extern int kernel_address_add_ipv4(struct interface *, struct connected *);
extern int kernel_address_delete_ipv4(struct interface *, struct connected *); extern int kernel_address_delete_ipv4(struct interface *, struct connected *);
extern int kernel_neigh_update(int, int, uint32_t, char *, int); extern int kernel_neigh_update(int, int, uint32_t, char *, int);
extern int kernel_interface_set_master(struct interface *master, extern int kernel_interface_set_master(struct interface *master,
struct interface *slave); struct interface *slave);
extern int kernel_add_lsp(zebra_lsp_t *);
extern int kernel_upd_lsp(zebra_lsp_t *); extern void kernel_add_lsp(zebra_lsp_t *lsp);
extern int kernel_del_lsp(zebra_lsp_t *); 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 mpls_kernel_init(void);
extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute); extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute);

View File

@ -1598,33 +1598,51 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
return suc; return suc;
} }
int kernel_route_rib(struct prefix *p, struct prefix *src_p, void kernel_route_rib(struct prefix *p, struct prefix *src_p,
struct route_entry *old, struct route_entry *new) struct route_entry *old, struct route_entry *new)
{ {
int ret = 0;
assert(old || new); assert(old || new);
if (!old && new) if (new) {
return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 0); if (p->family == AF_INET)
if (old && !new) ret = netlink_route_multipath(RTM_NEWROUTE, p, src_p,
return netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0); new, (old) ? 1 : 0);
else {
/*
* So v6 route replace semantics are not in
* the kernel at this point as I understand it.
* So let's do a delete than an add.
* In the future once v6 route replace semantics
* are in we can figure out what to do here to
* allow working with old and new kernels.
*
* I'm also intentionally ignoring the failure case
* of the route delete. If that happens yeah we're
* screwed.
*/
if (old)
netlink_route_multipath(RTM_DELROUTE, p,
src_p, old, 0);
ret = netlink_route_multipath(RTM_NEWROUTE, p,
src_p, new, 0);
}
kernel_route_rib_pass_fail(p, new,
(!ret) ?
SOUTHBOUND_INSTALL_SUCCESS :
SOUTHBOUND_INSTALL_FAILURE);
return;
}
if (p->family == AF_INET) if (old) {
return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 1); ret = netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0);
/* kernel_route_rib_pass_fail(p, old,
* So v6 route replace semantics are not in the kernel at this (!ret) ?
* point as I understand it. SOUTHBOUND_DELETE_SUCCESS :
* So let's do a delete than an add. SOUTHBOUND_DELETE_FAILURE);
* In the future once v6 route replace semantics are in }
* we can figure out what to do here to allow working
* with old and new kernels.
*
* I'm also intentionally ignoring the failure case
* of the route delete. If that happens yeah we're
* screwed.
*/
netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0);
return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 0);
} }
int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
@ -2414,17 +2432,6 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp)
_netlink_mpls_build_singlepath(routedesc, nhlfe, _netlink_mpls_build_singlepath(routedesc, nhlfe,
&req.n, &req.r, &req.n, &req.r,
sizeof req, cmd); 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++; nexthop_num++;
break; break;
} }
@ -2468,18 +2475,6 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp)
rta, rtnh, &req.r, rta, rtnh, &req.r,
&src1); &src1);
rtnh = RTNH_NEXT(rtnh); 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

@ -387,14 +387,14 @@ static int kernel_rtm(int cmd, struct prefix *p, struct route_entry *re)
return 0; return 0;
} }
int kernel_route_rib(struct prefix *p, struct prefix *src_p, void kernel_route_rib(struct prefix *p, struct prefix *src_p,
struct route_entry *old, struct route_entry *new) struct route_entry *old, struct route_entry *new)
{ {
int route = 0; int route = 0;
if (src_p && src_p->prefixlen) { if (src_p && src_p->prefixlen) {
zlog_err("route add: IPv6 sourcedest routes unsupported!"); zlog_err("route add: IPv6 sourcedest routes unsupported!");
return 1; return;
} }
if (zserv_privs.change(ZPRIVS_RAISE)) if (zserv_privs.change(ZPRIVS_RAISE))
@ -409,7 +409,17 @@ int kernel_route_rib(struct prefix *p, struct prefix *src_p,
if (zserv_privs.change(ZPRIVS_LOWER)) if (zserv_privs.change(ZPRIVS_LOWER))
zlog_err("Can't lower privileges"); zlog_err("Can't lower privileges");
return route; if (new) {
kernel_route_rib_pass_fail(p, new,
(!route) ?
SOUTHBOUND_INSTALL_SUCCESS :
SOUTHBOUND_INSTALL_FAILURE);
} else {
kernel_route_rib_pass_fail(p, old,
(!route) ?
SOUTHBOUND_DELETE_SUCCESS :
SOUTHBOUND_DELETE_FAILURE);
}
} }
int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,

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) static void lsp_uninstall_from_kernel(struct hash_backet *backet, void *ctxt)
{ {
int ret;
zebra_lsp_t *lsp; zebra_lsp_t *lsp;
lsp = (zebra_lsp_t *)backet->data; lsp = (zebra_lsp_t *)backet->data;
if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) { if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED))
ret = kernel_del_lsp(lsp); kernel_del_lsp(lsp);
if (!ret) {
UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
clear_nhlfe_installed(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) static wq_item_status lsp_process(struct work_queue *wq, void *data)
{ {
int ret = 1;
zebra_lsp_t *lsp; zebra_lsp_t *lsp;
zebra_nhlfe_t *oldbest, *newbest; zebra_nhlfe_t *oldbest, *newbest;
char buf[BUFSIZ], buf2[BUFSIZ]; char buf[BUFSIZ], buf2[BUFSIZ];
@ -905,12 +897,7 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
if (newbest) { if (newbest) {
UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED); UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED);
ret = kernel_add_lsp(lsp); kernel_add_lsp(lsp);
if (!ret)
SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
else
clear_nhlfe_installed(lsp);
zvrf->lsp_installs++; zvrf->lsp_installs++;
} }
@ -918,25 +905,38 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
/* Installed, may need an update and/or delete. */ /* Installed, may need an update and/or delete. */
if (!newbest) { if (!newbest) {
ret = kernel_del_lsp(lsp); kernel_del_lsp(lsp);
if (!ret) {
UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
clear_nhlfe_installed(lsp);
}
zvrf->lsp_removals++; zvrf->lsp_removals++;
} else if (CHECK_FLAG(lsp->flags, LSP_FLAG_CHANGED)) { } else if (CHECK_FLAG(lsp->flags, LSP_FLAG_CHANGED)) {
zebra_nhlfe_t *nhlfe;
struct nexthop *nexthop;
UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED); UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED);
UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
ret = kernel_upd_lsp(lsp); /*
* Any NHLFE that was installed but is not
* selected now needs to have its flags updated.
*/
for (nhlfe = lsp->nhlfe_list;
nhlfe; nhlfe = nhlfe->next) {
nexthop = nhlfe->nexthop;
if (!nexthop)
continue;
if (!ret) if (CHECK_FLAG(nhlfe->flags,
SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); NHLFE_FLAG_INSTALLED) &&
else !CHECK_FLAG(nhlfe->flags,
clear_nhlfe_installed(lsp); NHLFE_FLAG_SELECTED)) {
UNSET_FLAG(nhlfe->flags,
NHLFE_FLAG_INSTALLED);
UNSET_FLAG(nexthop->flags,
NEXTHOP_FLAG_FIB);
}
}
kernel_upd_lsp(lsp);
zvrf->lsp_installs++; zvrf->lsp_installs++;
} }
@ -1659,6 +1659,42 @@ static int mpls_processq_init(struct zebra_t *zebra)
/* Public functions */ /* 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 '/'. * String to label conversion, labels separated by '/'.
* *

View File

@ -29,16 +29,21 @@
/* /*
* Install Label Forwarding entry into the kernel. * 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; int ret;
if (!lsp || !lsp->best_nhlfe) // unexpected if (!lsp || !lsp->best_nhlfe) { // unexpected
return -1; kernel_lsp_pass_fail(lsp, SOUTHBOUND_INSTALL_FAILURE);
return;
}
ret = netlink_mpls_multipath(RTM_NEWROUTE, lsp); ret = netlink_mpls_multipath(RTM_NEWROUTE, lsp);
return ret; kernel_lsp_pass_fail(lsp,
(!ret) ?
SOUTHBOUND_INSTALL_SUCCESS :
SOUTHBOUND_INSTALL_FAILURE);
} }
/* /*
@ -52,51 +57,48 @@ int kernel_add_lsp(zebra_lsp_t *lsp)
* through the metric field (before kernel-MPLS). This shouldn't be an issue * through the metric field (before kernel-MPLS). This shouldn't be an issue
* any longer, so REPLACE can be reintroduced. * 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; int ret;
zebra_nhlfe_t *nhlfe;
struct nexthop *nexthop;
if (!lsp || !lsp->best_nhlfe) // unexpected if (!lsp || !lsp->best_nhlfe) { // unexpected
return -1; 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.
*/
for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
nexthop = nhlfe->nexthop;
if (!nexthop)
continue;
if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) &&
!CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)) {
UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
}
} }
ret = netlink_mpls_multipath(RTM_NEWROUTE, 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. * 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; int ret;
if (!lsp) // unexpected if (!lsp) { // unexpected
return -1; kernel_lsp_pass_fail(lsp,
SOUTHBOUND_DELETE_FAILURE);
return;
}
if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) {
return -1; kernel_lsp_pass_fail(lsp,
SOUTHBOUND_DELETE_FAILURE);
return;
}
ret = netlink_mpls_multipath(RTM_DELROUTE, lsp); 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) int mpls_kernel_init(void)

View File

@ -24,17 +24,17 @@
#if !defined(HAVE_NETLINK) && !defined(OPEN_BSD) #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) int mpls_kernel_init(void)
{ {

View File

@ -279,56 +279,69 @@ static int kernel_lsp_cmd(int action, zebra_lsp_t *lsp)
default: default:
break; 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); return (0);
} }
int kernel_add_lsp(zebra_lsp_t *lsp) void kernel_add_lsp(zebra_lsp_t *lsp)
{ {
int ret; int ret;
if (!lsp || !lsp->best_nhlfe) // unexpected if (!lsp || !lsp->best_nhlfe) { // unexpected
return -1; kernel_lsp_pass_fail(lsp, SOUTHBOUND_INSTALL_FAILURE);
return;
}
ret = kernel_lsp_cmd(RTM_ADD, lsp); 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; int ret;
if (!lsp || !lsp->best_nhlfe) // unexpected if (!lsp || !lsp->best_nhlfe) { // unexpected
return -1; kernel_lsp_pass_fail(lsp, SOUTHBOUND_INSTALL_FAILURE);
return;
}
ret = kernel_lsp_cmd(RTM_CHANGE, lsp); 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; int ret;
if (!lsp) // unexpected if (!lsp) { // unexpected
return -1; kernel_lsp_pass_fail(lsp,
SOUTHBOUND_DELETE_FAILURE);
return;
}
if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) {
return -1; kernel_lsp_pass_fail(lsp,
SOUTHBOUND_DELETE_FAILURE);
return;
}
ret = kernel_lsp_cmd(RTM_DELETE, lsp); 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) static int kmpw_install(struct zebra_pw *pw)

View File

@ -993,13 +993,49 @@ int zebra_rib_labeled_unicast(struct route_entry *re)
return 1; return 1;
} }
void kernel_route_rib_pass_fail(struct prefix *p, struct route_entry *re,
enum southbound_results res)
{
struct nexthop *nexthop;
char buf[PREFIX_STRLEN];
switch (res) {
case SOUTHBOUND_INSTALL_SUCCESS:
for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
continue;
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
else
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
}
zsend_route_notify_owner(re->type, re->instance, re->vrf_id,
p, ZAPI_ROUTE_INSTALLED);
break;
case SOUTHBOUND_INSTALL_FAILURE:
zsend_route_notify_owner(re->type, re->instance, re->vrf_id,
p, ZAPI_ROUTE_FAIL_INSTALL);
zlog_warn("%u:%s: Route install failed", re->vrf_id,
prefix2str(p, buf, sizeof(buf)));
break;
case SOUTHBOUND_DELETE_SUCCESS:
for (ALL_NEXTHOPS(re->nexthop, nexthop))
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
break;
case SOUTHBOUND_DELETE_FAILURE:
zlog_warn("%u:%s: Route Deletion failure", re->vrf_id,
prefix2str(p, buf, sizeof(buf)));
break;
}
}
/* Update flag indicates whether this is a "replace" or not. Currently, this /* Update flag indicates whether this is a "replace" or not. Currently, this
* is only used for IPv4. * is only used for IPv4.
*/ */
int rib_install_kernel(struct route_node *rn, struct route_entry *re, void rib_install_kernel(struct route_node *rn, struct route_entry *re,
struct route_entry *old) struct route_entry *old)
{ {
int ret = 0;
struct nexthop *nexthop; struct nexthop *nexthop;
rib_table_info_t *info = srcdest_rnode_table_info(rn); rib_table_info_t *info = srcdest_rnode_table_info(rn);
struct prefix *p, *src_p; struct prefix *p, *src_p;
@ -1010,7 +1046,7 @@ int rib_install_kernel(struct route_node *rn, struct route_entry *re,
if (info->safi != SAFI_UNICAST) { if (info->safi != SAFI_UNICAST) {
for (ALL_NEXTHOPS(re->nexthop, nexthop)) for (ALL_NEXTHOPS(re->nexthop, nexthop))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
return ret; return;
} else { } else {
struct nexthop *prev; struct nexthop *prev;
@ -1042,33 +1078,15 @@ int rib_install_kernel(struct route_node *rn, struct route_entry *re,
* the kernel. * the kernel.
*/ */
hook_call(rib_update, rn, "installing in kernel"); hook_call(rib_update, rn, "installing in kernel");
ret = kernel_route_rib(p, src_p, old, re); kernel_route_rib(p, src_p, old, re);
zvrf->installs++; zvrf->installs++;
/* If install succeeds, update FIB flag for nexthops. */ return;
if (!ret) {
for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
continue;
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
else
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
}
zsend_route_notify_owner(re->type, re->instance, re->vrf_id,
p, ZAPI_ROUTE_INSTALLED);
} else
zsend_route_notify_owner(re->type, re->instance, re->vrf_id,
p, ZAPI_ROUTE_FAIL_INSTALL);
return ret;
} }
/* Uninstall the route from kernel. */ /* Uninstall the route from kernel. */
int rib_uninstall_kernel(struct route_node *rn, struct route_entry *re) void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
{ {
int ret = 0;
struct nexthop *nexthop; struct nexthop *nexthop;
rib_table_info_t *info = srcdest_rnode_table_info(rn); rib_table_info_t *info = srcdest_rnode_table_info(rn);
struct prefix *p, *src_p; struct prefix *p, *src_p;
@ -1079,7 +1097,7 @@ int rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
if (info->safi != SAFI_UNICAST) { if (info->safi != SAFI_UNICAST) {
for (ALL_NEXTHOPS(re->nexthop, nexthop)) for (ALL_NEXTHOPS(re->nexthop, nexthop))
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
return ret; return;
} }
/* /*
@ -1087,13 +1105,10 @@ int rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
* the kernel. * the kernel.
*/ */
hook_call(rib_update, rn, "uninstalling from kernel"); hook_call(rib_update, rn, "uninstalling from kernel");
ret = kernel_route_rib(p, src_p, re, NULL); kernel_route_rib(p, src_p, re, NULL);
zvrf->removals++; zvrf->removals++;
for (ALL_NEXTHOPS(re->nexthop, nexthop)) return;
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
return ret;
} }
/* Uninstall the route from kernel. */ /* Uninstall the route from kernel. */
@ -1207,14 +1222,8 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
if (zebra_rib_labeled_unicast(new)) if (zebra_rib_labeled_unicast(new))
zebra_mpls_lsp_install(zvrf, rn, new); zebra_mpls_lsp_install(zvrf, rn, new);
if (!RIB_SYSTEM_ROUTE(new)) { if (!RIB_SYSTEM_ROUTE(new))
if (rib_install_kernel(rn, new, NULL)) { rib_install_kernel(rn, new, NULL);
char buf[SRCDEST2STR_BUFFER];
srcdest_rnode2str(rn, buf, sizeof(buf));
zlog_warn("%u:%s: Route install failed", zvrf_id(zvrf),
buf);
}
}
UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED);
} }
@ -1301,13 +1310,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
if (zebra_rib_labeled_unicast(new)) if (zebra_rib_labeled_unicast(new))
zebra_mpls_lsp_install(zvrf, rn, new); zebra_mpls_lsp_install(zvrf, rn, new);
if (rib_install_kernel(rn, new, old)) { rib_install_kernel(rn, new, old);
char buf[SRCDEST2STR_BUFFER];
srcdest_rnode2str(rn, buf, sizeof(buf));
installed = 0;
zlog_warn("%u:%s: Route install failed",
zvrf_id(zvrf), buf);
}
} }
/* If install succeeded or system route, cleanup flags /* If install succeeded or system route, cleanup flags
@ -2633,7 +2636,6 @@ static void rib_sweep_table(struct route_table *table)
struct route_entry *re; struct route_entry *re;
struct route_entry *next; struct route_entry *next;
struct nexthop *nexthop; struct nexthop *nexthop;
int ret = 0;
if (!table) if (!table)
return; return;
@ -2670,9 +2672,8 @@ static void rib_sweep_table(struct route_table *table)
for (ALL_NEXTHOPS(re->nexthop, nexthop)) for (ALL_NEXTHOPS(re->nexthop, nexthop))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
ret = rib_uninstall_kernel(rn, re); rib_uninstall_kernel(rn, re);
if (!ret) rib_delnode(rn, re);
rib_delnode(rn, re);
} }
} }
} }