Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Local connected #16300

Merged
merged 5 commits into from
Aug 28, 2024
Merged

Local connected #16300

merged 5 commits into from
Aug 28, 2024

Conversation

donaldsharp
Copy link
Member

Allow kernel routes to be read in when they are created in linux. Additionally treat the connected routes as connected. This fixes one of the issues seen with NOPREFIXROUTE

@@ -1599,7 +1599,8 @@ static void zebra_rib_fixup_system(struct route_node *rn)
}

/* Route comparison logic, with various special cases. */
static bool rib_compare_routes(const struct route_entry *re1,
static bool rib_compare_routes(const struct route_node *rn,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't see "rn" used?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah that is left over from some debugging I added.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@@ -1619,6 +1620,11 @@ 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 &&
re2->type == ZEBRA_ROUTE_CONNECT) &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we already tested that the two types are equal - can just test either re1 or re2?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, fixed

struct interface *ifp;

if (p->family == AF_INET6 &&
IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting - don't protocols sometimes want to know about the link-locals though?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not as a kernel route. We already have code that handles the link locals. This is just a special case for how we are receiving the v6 LL routes from the kernel as far as I can tell.

zebra/zebra_rib.c Show resolved Hide resolved
}

if (!alive) {
struct rib_table_info *rib_table = srcdest_rnode_table_info(rn);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems a little too bad to have to do these lookups for each prefix - could we pass something useful down from rib_update_table or rib_update_route_node, like the afi/safi?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at that and it was adding several layers of parameters. Just seemed very very easy to look it up in this special case instead of changing a whole bunch of functions to just pass afi/safi in for the !alive case( which should not be many routes)

Copy link
Member

@riw777 riw777 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good

@riw777
Copy link
Member

riw777 commented Jul 2, 2024

looks like this might be related --

E   AssertionError: Testcase test_verify_default_originate_after_BGP_and_FRR_restart_p2 : Failed : Redistributed routes from R0 is not learned in Router R1 RIB 
Error: Missing route in RIB of router r1, routes: ['2001:db8:f::1:17/128']
assert "Missing route in RIB of router r1, routes: ['2001:db8:f::1:17/128']\n" is True

but I'm trying to rerun just that test again to make certain

ifp = if_lookup_prefix(p, re->vrf_id);
if (ifp) {
if (ifp->ifindex == ng->nexthop->ifindex)
re->type = ZEBRA_ROUTE_CONNECT;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this only considers a route to be connected if it exactly matches a prefix installed on the interface. However, the kernel is perfectly happy to accept "connected" prefixes where this is not the case (and routing works just fine with them):

# ip -br a
lo               UNKNOWN        127.0.0.1/8 ::1/128 
veth0@if5        UP             10.10.10.10/32 fe80::2ceb:48ff:fe4a:954f/64
# ip r
# ip r add 10.1.1.0/24 dev veth0
# ip r add 10.10.10.11/32 dev veth0
# ip r add default dev veth0
# ip r
default dev veth0 scope link 
10.1.1.0/24 dev veth0 scope link 
10.10.10.11 dev veth0 scope link 
# ping -c 1 10.1.1.1
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=0.072 ms

--- 10.1.1.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.072/0.072/0.072/0.000 ms

So with that in mind, wouldn't it be better to use the kernel's notion of a connected route (scope link) to set the ZEBRA_ROUTE_CONNECT type, instead of using this heuristic? That's the approach I took in #16418 for the same reason, but cf the discussion there, it's probably easier to incorporate that bit into this PR? :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer that we keep things the way we have them as that this is how we think about the problem in FRR. I'm not sure that it matters though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to clarify, my point a bit more. I do not want any route that has link scope to become a connected route. A connected route is a route that has an address associated with it on the interface in question. That is the definition that I want to stick with.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, okay. My concern was mostly that by not mirroring the exact semantics of the kernel FRR can end up with a different view of how packets will be routed than what the forwarding plane actually does. However, I don't have a concrete use case where this will lead to problems, and I guess for the original "set noprefixroute but install another replacement route for the prefix in the kernel" use case, this is fine :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

be aware that this patch will just turn those local scope routes into kernel routes so nothing to worry about

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, right, so FRR will still end up with a consistent view of the forwarding state (because it no longer skips all RTPROT_KERNEL routes), but only those with a matching interface prefix will be considered connected? Makes sense!

@frrbot frrbot bot added the tests Topotests, make check, etc label Aug 15, 2024

rib_delete(rib_table->afi, rib_table->safi, re->vrf_id,
re->type, re->instance, re->flags, p, src_p, NULL, 0,
re->table, re->metric, re->distance, true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that last "true" is the "fromkernel" boolean, right? Will that cause problems, since that usually indicates an update arriving from the kernel, where this is an update that zebra is generating?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this code path I intentionally wanted to hit the code in zebra_rib.c:

	if (same) {
		struct nexthop *tmp_nh;

		if (ere->fromkernel &&
		    CHECK_FLAG(ere->re->flags, ZEBRA_FLAG_SELFROUTE) &&
		    !zrouter.allow_delete) {
			rib_install_kernel(rn, same, NULL);
			route_unlock_node(rn);

			early_route_memory_free(ere);
			return;
		}```

if (rn->info &&
CHECK_FLAG(rib_dest_from_rnode(rn)->flags,
RIB_ROUTE_ANY_QUEUED) &&
event != RIB_UPDATE_INTERFACE_DOWN)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could the comment be updated a bit to explain this added test?
are there any possible ordering problems, if the dest is already queued for processing, and then we enqueue a delete event in rib_update_handle_kernel_route_down_possibility() ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -1058,6 +1058,8 @@ void if_down(struct interface *ifp)

/* Delete all neighbor addresses learnt through IPv6 RA */
if_down_del_nbr_connected(ifp);

rib_update_handle_vrf_all(RIB_UPDATE_INTERFACE_DOWN, ZEBRA_ROUTE_KERNEL);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this is going to do this processing synchronously. that "handle_vrf_all()" is currently an async event callback, via "rib_update()": why not use that path to do the work? was there some issue with doing it async?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that whole system area is a mess of code. I was just hooking into it quickly. I need to rethink that whole mess if we want to do it async. Although I am not sure it matters at this point in time. Can I add it to the list of things that needs to be reworked and rethought?

The prefix'es p and src_p are not const.  Let's make
them so.  Useful to signal that we will not change this
data.

Signed-off-by: Donald Sharp <[email protected]>
This function will be used on interface down
events to allow for kernel routes to be cleaned
up.

Signed-off-by: Donald Sharp <[email protected]>
Current code intentionally ignores kernel routes.  Modify
zebra to allow these routes to be read in on linux.  Also
modify zebra to look to see if a route should be treated
as a connected and mark it as such.

Additionally this should properly handle some of the issues
being seen with NOPREFIXROUTE.

Signed-off-by: Donald Sharp <[email protected]>
There exists a path in rib_add_multipath where if a decision
is made to not use the passed in re, we just drop the memory
instead of freeing it.  Let's free it.

Signed-off-by: Donald Sharp <[email protected]>
a) A noprefix address by itself should not create a connected route.
   This was pre-existing.
b) A noprefix address with a corresponding route should result in a
   connected route.  This is how NetworkManager appears to work.
   This is new behavior, so a new test.
c) A route is added to the system from someone else.
   This is new behavior, so a new test.

Signed-off-by: Donald Sharp <[email protected]>
Copy link
Contributor

@mjstapp mjstapp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, approving

@mjstapp mjstapp merged commit 8b23abf into FRRouting:master Aug 28, 2024
11 checks passed
Jafaral added a commit that referenced this pull request Nov 12, 2024
New Features Highlight:

- PIM candidate BSR/RP [#16438]
- Static IGMP join without an IGMP report [1#6450]
- PIM AutoRP discovery/announcements [#16634]
- IGMP proxy [#16861]
- SRv6 SID Manager [#15604]
- Add `bgp ipv6-auto-ra` command [#16354]
- Implement `neighbor x remote-as auto` for BGP [#16345]
- Implement `bgp dual-as` for BGP [#16816]
- Implement BGP-wide configuration for graceful restart [#16099]
- Handle kernel routes appropriately (should fix recent NOPREFIXROUTE issue) [#16300]
- Add `cisco-authentication` password support for NHRP [#16172]

Signed-off-by: Jafar Al-Gharaibeh <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
master size/L tests Topotests, make check, etc zebra
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants