summaryrefslogtreecommitdiff
path: root/zebra/zebra_rib.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_rib.c')
-rw-r--r--zebra/zebra_rib.c113
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. */