mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-16 20:43:41 +00:00
Merge pull request #1496 from donaldsharp/install_failure
Additional Southbound API changes
This commit is contained in:
commit
50a0033c24
@ -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
|
||||||
|
52
zebra/rt.h
52
zebra/rt.h
@ -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);
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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 '/'.
|
||||||
*
|
*
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user