summaryrefslogtreecommitdiff
path: root/zebra/zebra_rib.c
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@nvidia.com>2023-01-04 18:32:43 -0500
committerDonald Sharp <sharpd@nvidia.com>2023-11-01 17:13:06 -0400
commitd4aa24ba7df066ee8a9f4bab5c1b4e9ff8474392 (patch)
tree250831364f85b54568614167d4b6bf118348c632 /zebra/zebra_rib.c
parent8e3a96e846a15f34384a20a3ede2e894d7e97253 (diff)
*: Introduce Local Host Routes to FRR
Create Local routes in FRR: S 0.0.0.0/0 [1/0] via 192.168.119.1, enp39s0, weight 1, 00:03:46 K>* 0.0.0.0/0 [0/100] via 192.168.119.1, enp39s0, 00:03:51 O 192.168.119.0/24 [110/100] is directly connected, enp39s0, weight 1, 00:03:46 C>* 192.168.119.0/24 is directly connected, enp39s0, 00:03:51 L>* 192.168.119.224/32 is directly connected, enp39s0, 00:03:51 O 192.168.119.229/32 [110/100] via 0.0.0.0, enp39s0 inactive, weight 1, 00:03:46 C>* 192.168.119.229/32 is directly connected, enp39s0, 00:03:46 Create ability to redistribute local routes. Modify tests to support this change. Signed-off-by: Donald Sharp <sharpd@nvidia.com>
Diffstat (limited to 'zebra/zebra_rib.c')
-rw-r--r--zebra/zebra_rib.c79
1 files changed, 54 insertions, 25 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 37c042c044..3b1da21d35 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -103,6 +103,9 @@ static const struct {
[ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT,
ZEBRA_CONNECT_DISTANCE_DEFAULT,
META_QUEUE_CONNECTED},
+ [ZEBRA_ROUTE_LOCAL] = {ZEBRA_ROUTE_LOCAL,
+ ZEBRA_CONNECT_DISTANCE_DEFAULT,
+ META_QUEUE_CONNECTED},
[ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC,
ZEBRA_STATIC_DISTANCE_DEFAULT,
META_QUEUE_STATIC},
@@ -522,7 +525,8 @@ struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
if (rn)
route_lock_node(rn);
} else {
- if (match->type != ZEBRA_ROUTE_CONNECT) {
+ if (match->type != ZEBRA_ROUTE_CONNECT &&
+ match->type != ZEBRA_ROUTE_LOCAL) {
if (!CHECK_FLAG(match->status,
ROUTE_ENTRY_INSTALLED))
return NULL;
@@ -624,7 +628,8 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
if (!match)
return NULL;
- if (match->type == ZEBRA_ROUTE_CONNECT)
+ if (match->type == ZEBRA_ROUTE_CONNECT ||
+ match->type == ZEBRA_ROUTE_LOCAL)
return match;
if (CHECK_FLAG(match->status, ROUTE_ENTRY_INSTALLED))
@@ -1123,27 +1128,15 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED);
}
-/* Check if 'alternate' RIB entry is better than 'current'. */
-static struct route_entry *rib_choose_best(struct route_entry *current,
- struct route_entry *alternate)
+static struct route_entry *rib_choose_best_type(uint8_t route_type,
+ struct route_entry *current,
+ struct route_entry *alternate)
{
- if (current == NULL)
- return alternate;
-
- /* 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. 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.
+ /*
+ * We know that alternate and current are now non-NULL
*/
- if (alternate->type == ZEBRA_ROUTE_CONNECT) {
- if (current->type != ZEBRA_ROUTE_CONNECT)
+ if (alternate->type == route_type) {
+ if (current->type != route_type)
return alternate;
/* both are connected. are either loop or vrf? */
@@ -1172,7 +1165,41 @@ static struct route_entry *rib_choose_best(struct route_entry *current,
return current;
}
- if (current->type == ZEBRA_ROUTE_CONNECT)
+ return NULL;
+}
+
+/* Check if 'alternate' RIB entry is better than 'current'. */
+static struct route_entry *rib_choose_best(struct route_entry *current,
+ struct route_entry *alternate)
+{
+ struct route_entry *possible;
+
+ if (current == NULL)
+ return alternate;
+
+ /* filter route selection in following order:
+ * - Local beats Connected
+ * - 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 or Local 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.
+ */
+ possible = rib_choose_best_type(ZEBRA_ROUTE_LOCAL, current, alternate);
+ if (possible)
+ return possible;
+
+ possible = rib_choose_best_type(ZEBRA_ROUTE_CONNECT, current, alternate);
+ if (possible)
+ return possible;
+
+ if (current->type == ZEBRA_ROUTE_CONNECT ||
+ current->type == ZEBRA_ROUTE_LOCAL)
return current;
/* higher distance loses */
@@ -1507,7 +1534,8 @@ static bool rib_route_match_ctx(const struct route_entry *re,
} else if (re->type == ZEBRA_ROUTE_KERNEL &&
re->metric != dplane_ctx_get_metric(ctx)) {
result = false;
- } else if (re->type == ZEBRA_ROUTE_CONNECT) {
+ } else if (re->type == ZEBRA_ROUTE_CONNECT ||
+ re->type == ZEBRA_ROUTE_LOCAL) {
result = nexthop_group_equal_no_recurse(
&re->nhe->nhg, dplane_ctx_get_ng(ctx));
}
@@ -1565,7 +1593,7 @@ static bool rib_compare_routes(const struct route_entry *re1,
* v6 link-locals, and we also support multiple addresses in the same
* subnet on a single interface.
*/
- if (re1->type != ZEBRA_ROUTE_CONNECT)
+ if (re1->type != ZEBRA_ROUTE_CONNECT && re1->type != ZEBRA_ROUTE_LOCAL)
return true;
return false;
@@ -2968,7 +2996,8 @@ static void process_subq_early_route_delete(struct zebra_early_route *ere)
if (re->type == ZEBRA_ROUTE_KERNEL &&
re->metric != ere->re->metric)
continue;
- if (re->type == ZEBRA_ROUTE_CONNECT &&
+ if ((re->type == ZEBRA_ROUTE_CONNECT ||
+ re->type == ZEBRA_ROUTE_LOCAL) &&
(rtnh = re->nhe->nhg.nexthop) &&
rtnh->type == NEXTHOP_TYPE_IFINDEX && nh) {
if (rtnh->ifindex != nh->ifindex)