summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/zebra.h1
-rw-r--r--zebra/rib.h1
-rw-r--r--zebra/zebra_fpm.c2
-rw-r--r--zebra/zebra_rib.c82
-rw-r--r--zebra/zebra_vty.c4
-rw-r--r--zebra/zserv.c12
6 files changed, 71 insertions, 31 deletions
diff --git a/lib/zebra.h b/lib/zebra.h
index 1754b34d..d9802830 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -459,6 +459,7 @@ extern const char *zserv_command_string (unsigned int command);
#define ZEBRA_FLAG_BLACKHOLE 0x04
#define ZEBRA_FLAG_IBGP 0x08
#define ZEBRA_FLAG_SELECTED 0x10
+#define ZEBRA_FLAG_FIB_OVERRIDE 0x20
#define ZEBRA_FLAG_STATIC 0x40
#define ZEBRA_FLAG_REJECT 0x80
diff --git a/zebra/rib.h b/zebra/rib.h
index ffe7e2ff..67ffe8de 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -83,6 +83,7 @@ struct rib
u_char status;
#define RIB_ENTRY_REMOVED (1 << 0)
#define RIB_ENTRY_CHANGED (1 << 1)
+#define RIB_ENTRY_SELECTED_FIB (1 << 2)
/* Nexthop information. */
u_char nexthop_num;
diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c
index 292dbb63..cb04f21a 100644
--- a/zebra/zebra_fpm.c
+++ b/zebra/zebra_fpm.c
@@ -889,7 +889,7 @@ zfpm_route_for_update (rib_dest_t *dest)
RIB_DEST_FOREACH_ROUTE (dest, rib)
{
- if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
+ if (!CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
continue;
return rib;
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 92640872..d06382c3 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -387,7 +387,7 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
{
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
continue;
- if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
+ if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
break;
}
@@ -521,7 +521,7 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
{
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
continue;
- if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
+ if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
break;
}
@@ -633,7 +633,7 @@ rib_match_ipv4_safi (struct in_addr addr, safi_t safi, int skip_bgp,
{
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
continue;
- if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
+ if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
break;
}
@@ -778,7 +778,7 @@ rib_lookup_ipv4 (struct prefix_ipv4 *p, vrf_id_t vrf_id)
{
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
continue;
- if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
+ if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
break;
}
@@ -838,7 +838,7 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate,
{
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
continue;
- if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
+ if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
break;
}
@@ -904,7 +904,7 @@ rib_match_ipv6 (struct in6_addr *addr, vrf_id_t vrf_id)
{
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
continue;
- if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
+ if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
break;
}
@@ -1139,7 +1139,7 @@ rib_uninstall (struct route_node *rn, struct rib *rib)
{
rib_table_info_t *info = rn->table->info;
- if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
+ if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
{
if (info->safi == SAFI_UNICAST)
zfpm_trigger_update (rn, "rib_uninstall");
@@ -1259,6 +1259,8 @@ rib_process (struct route_node *rn)
{
struct rib *rib;
struct rib *next;
+ struct rib *old_selected = NULL;
+ struct rib *new_selected = NULL;
struct rib *old_fib = NULL;
struct rib *new_fib = NULL;
int installed = 0;
@@ -1275,6 +1277,11 @@ rib_process (struct route_node *rn)
/* Currently installed rib. */
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
{
+ assert (old_selected == NULL);
+ old_selected = rib;
+ }
+ if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
+ {
assert (old_fib == NULL);
old_fib = rib;
}
@@ -1291,17 +1298,31 @@ rib_process (struct route_node *rn)
if (rib->distance == DISTANCE_INFINITY)
continue;
- new_fib = rib_choose_best(new_fib, rib);
+ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_FIB_OVERRIDE))
+ new_fib = rib_choose_best(new_fib, rib);
+ else
+ new_selected = rib_choose_best(new_selected, rib);
} /* RNODE_FOREACH_RIB_SAFE */
+ /* If no FIB override route, use the selected route also for FIB */
+ if (new_fib == NULL)
+ new_fib = new_selected;
+
/* After the cycle is finished, the following pointers will be set:
- * old_fib --- RIB entry currently having SELECTED
- * new_fib --- RIB entry that is newly SELECTED
+ * old_selected --- RIB entry currently having SELECTED
+ * new_selected --- RIB entry that is newly SELECTED
+ * old_fib --- RIB entry currently in kernel FIB
+ * new_fib --- RIB entry that is newly to be in kernel FIB
+ *
+ * new_selected will get SELECTED flag, and is going to be redistributed
+ * the zclients. new_fib (which can be new_selected) will be installed in kernel.
*/
/* Set real nexthops. */
if (new_fib)
nexthop_active_update (rn, new_fib, 1);
+ if (new_selected && new_selected != new_fib)
+ nexthop_active_update (rn, new_selected, 1);
/* Update kernel if FIB entry has changed */
if (old_fib != new_fib
@@ -1309,20 +1330,15 @@ rib_process (struct route_node *rn)
{
if (old_fib && old_fib != new_fib)
{
- if (! new_fib)
- redistribute_delete (&rn->p, old_fib);
-
if (! RIB_SYSTEM_ROUTE (old_fib) && (! new_fib || RIB_SYSTEM_ROUTE (new_fib)))
rib_update_kernel (rn, old_fib, NULL);
- UNSET_FLAG (old_fib->flags, ZEBRA_FLAG_SELECTED);
+ UNSET_FLAG (old_fib->status, RIB_ENTRY_SELECTED_FIB);
}
if (new_fib)
{
/* Install new or replace existing FIB entry */
- SET_FLAG (new_fib->flags, ZEBRA_FLAG_SELECTED);
- redistribute_add (&rn->p, new_fib);
-
+ SET_FLAG (new_fib->status, RIB_ENTRY_SELECTED_FIB);
if (! RIB_SYSTEM_ROUTE (new_fib))
rib_update_kernel (rn, old_fib, new_fib);
}
@@ -1346,6 +1362,26 @@ rib_process (struct route_node *rn)
rib_update_kernel (rn, NULL, new_fib);
}
+ /* Redistribute SELECTED entry */
+ if (old_selected != new_selected
+ || (new_selected && CHECK_FLAG (new_selected->status, RIB_ENTRY_CHANGED)))
+ {
+ if (old_selected)
+ {
+ if (! new_selected)
+ redistribute_delete (&rn->p, old_selected);
+ if (old_selected != new_selected)
+ UNSET_FLAG (old_selected->flags, ZEBRA_FLAG_SELECTED);
+ }
+
+ if (new_selected)
+ {
+ /* Install new or replace existing redistributed entry */
+ SET_FLAG (new_selected->flags, ZEBRA_FLAG_SELECTED);
+ redistribute_add (&rn->p, new_selected);
+ }
+ }
+
/* Remove all RIB entries queued for removal */
RNODE_FOREACH_RIB_SAFE (rn, rib, next)
{
@@ -1947,7 +1983,7 @@ void rib_lookup_and_pushup (struct prefix_ipv4 * p)
*/
RNODE_FOREACH_RIB (rn, rib)
{
- if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
+ if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB) &&
! RIB_SYSTEM_ROUTE (rib))
{
changed = 1;
@@ -2098,7 +2134,7 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
continue;
- if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
+ if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
fib = rib;
if (rib->type != type)
@@ -2146,7 +2182,7 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
- UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
+ UNSET_FLAG (fib->status, RIB_ENTRY_SELECTED_FIB);
}
else
{
@@ -2675,7 +2711,7 @@ rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
continue;
- if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
+ if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
fib = rib;
if (rib->type != type)
@@ -2724,7 +2760,7 @@ rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
- UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
+ UNSET_FLAG (fib->status, RIB_ENTRY_SELECTED_FIB);
}
else
{
@@ -3058,7 +3094,7 @@ rib_close_table (struct route_table *table)
for (rn = route_top (table); rn; rn = route_next (rn))
RNODE_FOREACH_RIB (rn, rib)
{
- if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
+ if (!CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
continue;
if (info->safi == SAFI_UNICAST)
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 656f55d4..21b92ea9 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -1295,6 +1295,10 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast)
vty_out (vty, ", vrf %u", rib->vrf_id);
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
vty_out (vty, ", best");
+ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_FIB_OVERRIDE))
+ vty_out (vty, ", fib-override");
+ if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
+ vty_out (vty, ", fib");
if (rib->refcnt)
vty_out (vty, ", refcnt %ld", rib->refcnt);
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 7a75ed42..600b0e5c 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -397,8 +397,7 @@ zsend_route_multipath (int cmd, struct zserv *client, struct prefix *p,
for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
{
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
- || nexthop_has_fib_child(nexthop))
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
{
SET_FLAG (zapi_flags, ZAPI_MESSAGE_NEXTHOP);
SET_FLAG (zapi_flags, ZAPI_MESSAGE_IFINDEX);
@@ -504,7 +503,7 @@ zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr,
* are looking up. Therefore, we will just iterate over the top
* chain of nexthops. */
for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
+ if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
{
stream_putc (s, nexthop->type);
switch (nexthop->type)
@@ -574,7 +573,7 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr,
* are looking up. Therefore, we will just iterate over the top
* chain of nexthops. */
for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
+ if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
{
stream_putc (s, nexthop->type);
switch (nexthop->type)
@@ -644,7 +643,7 @@ zsend_ipv4_nexthop_lookup_mrib (struct zserv *client, struct in_addr addr,
* are looking up. Therefore, we will just iterate over the top
* chain of nexthops. */
for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
+ if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
{
stream_putc (s, nexthop->type);
switch (nexthop->type)
@@ -709,8 +708,7 @@ zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p,
nump = stream_get_endp(s);
stream_putc (s, 0);
for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
- || nexthop_has_fib_child(nexthop))
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
{
stream_putc (s, nexthop->type);
switch (nexthop->type)