diff options
| author | Donald Sharp <sharpd@nvidia.com> | 2023-01-04 18:32:43 -0500 | 
|---|---|---|
| committer | Donald Sharp <sharpd@nvidia.com> | 2023-11-01 17:13:06 -0400 | 
| commit | d4aa24ba7df066ee8a9f4bab5c1b4e9ff8474392 (patch) | |
| tree | 250831364f85b54568614167d4b6bf118348c632 /zebra/zebra_rib.c | |
| parent | 8e3a96e846a15f34384a20a3ede2e894d7e97253 (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.c | 79 | 
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)  | 
