diff options
Diffstat (limited to 'zebra/zebra_rib.c')
| -rw-r--r-- | zebra/zebra_rib.c | 113 |
1 files changed, 76 insertions, 37 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 69f6ff9de7..ab07549ec2 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -20,37 +20,38 @@ #include <zebra.h> -#include "if.h" -#include "prefix.h" -#include "table.h" -#include "memory.h" -#include "zebra_memory.h" #include "command.h" +#include "if.h" +#include "linklist.h" #include "log.h" #include "log_int.h" -#include "sockunion.h" -#include "linklist.h" -#include "thread.h" -#include "workqueue.h" +#include "memory.h" +#include "mpls.h" +#include "nexthop.h" +#include "prefix.h" #include "prefix.h" #include "routemap.h" -#include "nexthop.h" -#include "vrf.h" -#include "mpls.h" +#include "sockunion.h" #include "srcdest_table.h" +#include "table.h" +#include "thread.h" +#include "vrf.h" +#include "workqueue.h" +#include "zebra/connected.h" +#include "zebra/debug.h" +#include "zebra/interface.h" +#include "zebra/redistribute.h" #include "zebra/rib.h" #include "zebra/rt.h" +#include "zebra/zapi_msg.h" +#include "zebra/zebra_errors.h" +#include "zebra/zebra_memory.h" #include "zebra/zebra_ns.h" -#include "zebra/zebra_vrf.h" -#include "zebra/redistribute.h" -#include "zebra/zebra_routemap.h" -#include "zebra/debug.h" #include "zebra/zebra_rnh.h" -#include "zebra/interface.h" -#include "zebra/connected.h" +#include "zebra/zebra_routemap.h" +#include "zebra/zebra_vrf.h" #include "zebra/zebra_vxlan.h" -#include "zebra/zapi_msg.h" DEFINE_HOOK(rib_update, (struct route_node * rn, const char *reason), (rn, reason)) @@ -1125,10 +1126,14 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re, hook_call(rib_update, rn, "installing in kernel"); switch (kernel_route_rib(rn, p, src_p, old, re)) { case DP_REQUEST_QUEUED: - zlog_err("No current known DataPlane interfaces can return this, please fix"); + flog_err( + ZEBRA_ERR_DP_INVALID_RC, + "No current known DataPlane interfaces can return this, please fix"); break; case DP_REQUEST_FAILURE: - zlog_err("No current known Rib Install Failure cases, please fix"); + flog_err( + ZEBRA_ERR_DP_INSTALL_FAIL, + "No current known Rib Install Failure cases, please fix"); break; case DP_REQUEST_SUCCESS: zvrf->installs++; @@ -1161,10 +1166,14 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re) hook_call(rib_update, rn, "uninstalling from kernel"); switch (kernel_route_rib(rn, p, src_p, re, NULL)) { case DP_REQUEST_QUEUED: - zlog_err("No current known DataPlane interfaces can return this, please fix"); + flog_err( + ZEBRA_ERR_DP_INVALID_RC, + "No current known DataPlane interfaces can return this, please fix"); break; case DP_REQUEST_FAILURE: - zlog_err("No current known RIB Install Failure cases, please fix"); + flog_err( + ZEBRA_ERR_DP_INSTALL_FAIL, + "No current known RIB Install Failure cases, please fix"); break; case DP_REQUEST_SUCCESS: if (zvrf) @@ -1492,17 +1501,37 @@ static struct route_entry *rib_choose_best(struct route_entry *current, /* filter route selection in following order: * - connected beats other types + * - if both connected, loopback or vrf wins * - lower distance beats higher * - lower metric beats higher for equal distance * - last, hence oldest, route wins tie break. */ - /* Connected routes. Pick the last connected + /* Connected routes. Check to see if either are a vrf + * or loopback interface. If not, pick the last connected * route of the set of lowest metric connected routes. */ if (alternate->type == ZEBRA_ROUTE_CONNECT) { - if (current->type != ZEBRA_ROUTE_CONNECT - || alternate->metric <= current->metric) + if (current->type != ZEBRA_ROUTE_CONNECT) + return alternate; + + /* both are connected. are either loop or vrf? */ + struct nexthop *nexthop = NULL; + + for (ALL_NEXTHOPS(alternate->ng, nexthop)) { + if (if_is_loopback_or_vrf(if_lookup_by_index( + nexthop->ifindex, alternate->vrf_id))) + return alternate; + } + + for (ALL_NEXTHOPS(current->ng, nexthop)) { + if (if_is_loopback_or_vrf(if_lookup_by_index( + nexthop->ifindex, current->vrf_id))) + return current; + } + + /* Neither are loop or vrf so pick best metric */ + if (alternate->metric <= current->metric) return alternate; return current; @@ -1936,7 +1965,8 @@ void rib_queue_add(struct route_node *rn) } if (zebrad.ribq == NULL) { - zlog_err("%s: work_queue does not exist!", __func__); + flog_err(ZEBRA_ERR_WQ_NONEXISTENT, + "%s: work_queue does not exist!", __func__); return; } @@ -1991,7 +2021,8 @@ static void rib_queue_init(struct zebra_t *zebra) if (!(zebra->ribq = work_queue_new(zebra->master, "route_node processing"))) { - zlog_err("%s: could not initialise work queue!", __func__); + flog_err(ZEBRA_ERR_WQ_NONEXISTENT, + "%s: could not initialise work queue!", __func__); return; } @@ -2004,7 +2035,8 @@ static void rib_queue_init(struct zebra_t *zebra) zebra->ribq->spec.hold = ZEBRA_RIB_PROCESS_HOLD_TIME; if (!(zebra->mq = meta_queue_new())) { - zlog_err("%s: could not initialise meta queue!", __func__); + flog_err(ZEBRA_ERR_WQ_NONEXISTENT, + "%s: could not initialise meta queue!", __func__); return; } return; @@ -2231,8 +2263,9 @@ void rib_lookup_and_dump(struct prefix_ipv4 *p, vrf_id_t vrf_id) /* Lookup table. */ table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); if (!table) { - zlog_err("%s:%u zebra_vrf_table() returned NULL", - __func__, vrf_id); + flog_err(ZEBRA_ERR_TABLE_LOOKUP_FAILED, + "%s:%u zebra_vrf_table() returned NULL", __func__, + vrf_id); return; } @@ -2278,8 +2311,9 @@ void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id) rib_dest_t *dest; if (NULL == (table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id))) { - zlog_err("%s:%u zebra_vrf_table() returned NULL", - __func__, vrf_id); + flog_err(ZEBRA_ERR_TABLE_LOOKUP_FAILED, + "%s:%u zebra_vrf_table() returned NULL", __func__, + vrf_id); return; } @@ -2637,8 +2671,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, } /* Schedule routes of a particular table (address-family) based on event. */ -static void rib_update_table(struct route_table *table, - rib_update_event_t event) +void rib_update_table(struct route_table *table, rib_update_event_t event) { struct route_node *rn; struct route_entry *re, *next; @@ -2718,12 +2751,18 @@ void rib_update(vrf_id_t vrf_id, rib_update_event_t event) /* Process routes of interested address-families. */ table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); - if (table) + if (table) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s : AFI_IP event %d", __func__, event); rib_update_table(table, event); + } table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id); - if (table) + if (table) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s : AFI_IP6 event %d", __func__, event); rib_update_table(table, event); + } } /* Delete self installed routes after zebra is relaunched. */ |
