Skip to content

Conversation

@cpaasch-oai
Copy link
Contributor

The goal is to allow setting a nexthop encapsulation on a nexthop object (and passing it down to the kernel). There already is an API to manipulate mpls encap on a route object. However, that API is exclusive to using rtnl_nexthop, while internally it is actually using a nh_encap.

Ideally, adding nexthop encaps is done all by using nh_encap objects (regardless of whether this is for a rtnl_nexthop or a rtnl_nh object. So, f1263ca is moving towards that direction. It also deprecated the previous rtnl_route_nh_encap_mpls() (and related APIs) as IMO a better way of handling this is by doing:

nh = rtnl_nh_encap_alloc()
rtnl_nh_encap_mpls(nh, ...)
rtnl_route_nh_set_encap(rtnh, nh)

The goal is to add full support for all types of nexthop encapsulations (ipvX tunnels, segment-routing,...). So, directly manipulating the nh_encap is cleaner.

Adding tests along the way, starting with a6a808b and from there on with each commit that is exposing new API.

For the tests to pass PR #442 is needed.

@cpaasch-oai
Copy link
Contributor Author

Thanks for the feedback. Will continue going through it in the coming days.

@cpaasch-oai cpaasch-oai force-pushed the t/nh_encap_generic branch 2 times, most recently from ff1eac8 to 517050a Compare August 15, 2025 20:54
Copy link
Owner

@thom311 thom311 left a comment

Choose a reason for hiding this comment

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

getting close. Thank you!

@cpaasch-oai cpaasch-oai force-pushed the t/nh_encap_generic branch 2 times, most recently from da612f8 to de3f0fd Compare August 21, 2025 21:23
@cpaasch-oai
Copy link
Contributor Author

@thom311 - as I fix the backwards compatibility for all callers of nh_encap_parse_msg I opted to not create nh_encap_parse_msg_safe and rather handle the NOSUPPORT directly in nh_encap_parse_msg. LMK if you prefer another approach.

I'm not sure here to what extend we want to preserve past behavior vs. becoming more backwards compatible.

@thom311
Copy link
Owner

thom311 commented Aug 21, 2025

@thom311 - as I fix the backwards compatibility for all callers of nh_encap_parse_msg I opted to not create nh_encap_parse_msg_safe and rather handle the NOSUPPORT directly in nh_encap_parse_msg. LMK if you prefer another approach.

OK, there is also

         if (!lwtunnel_encap_types[e_type].ops->parse_msg)
                  return -NLE_MSGTYPE_NOSUPPORT;

and

         if (e_type == LWTUNNEL_ENCAP_NONE) {
                  NL_DBG(2, "RTA_ENCAP_TYPE should not be LWTUNNEL_ENCAP_NONE\n");
                  return -NLE_INVAL;
         }

which I think warrant the same handling.

I'm not sure here to what extend we want to preserve past behavior vs. becoming more backwards compatible.

I think in general, unknown (or not implemented) attributes should be ignored. That is the only way to be forward compatible against future attributes. I don't think there is a lot of value in failing to parse unknown attributes (or unknown encap_type, in this case).

Copy link
Contributor

@KanjiMonster KanjiMonster left a comment

Choose a reason for hiding this comment

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

As a minor nitpick, I dislike brackets in commit subjects because anything in these get dropped by git-am when applying patches.

But that's just my preference.

Comment on lines -54 to +55
struct rtnl_nexthop *nh;
_nl_auto_rtnl_nexthop struct rtnl_nexthop *nh = NULL;
Copy link
Contributor

Choose a reason for hiding this comment

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

Switching to _nl_auto pointer should be a separate commit IMHO since this is unrelated to the changes according to the commit message, and makes reviewing harder.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point - I'm splitting out this commit.

Comment on lines -16 to +19
[LWTUNNEL_ENCAP_IP] = { .name = "ip" },
[LWTUNNEL_ENCAP_IP6] = { .name = "ip6" },
[LWTUNNEL_ENCAP_ILA] = { .name = "ila" },
[LWTUNNEL_ENCAP_BPF] = { .name = "bpf" },
[LWTUNNEL_ENCAP_IP] = { .name = "ip" },
[LWTUNNEL_ENCAP_IP6] = { .name = "ip6" },
[LWTUNNEL_ENCAP_ILA] = { .name = "ila" },
[LWTUNNEL_ENCAP_BPF] = { .name = "bpf" },
Copy link
Contributor

Choose a reason for hiding this comment

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

Likewise, being aligned around the equals sign seems to be a deliberate choice.

Unfortunately, the last time I checked there wasn't an option for that in clang-format.

return NULL;

return nh->rtnh_encap;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

missing empty line after the function

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed!

@cpaasch-oai
Copy link
Contributor Author

As a minor nitpick, I dislike brackets in commit subjects because anything in these get dropped by git-am when applying patches.

But that's just my preference.

Fair enough! I will stop doing that. I'm wondering now myself why did I even start doing that 😅

Don't do `if (...) expr;`. Always start a new line after the if().

Signed-off-by: Christoph Paasch <[email protected]>
Primarily getter/setter tests as well kernel round-trip.

Signed-off-by: Christoph Paasch <[email protected]>
The goal is to have struct rtnl_nh_encap be used for the route's nexthop
(In struct rtnl_nexthop) but also directly in an IP nexthop (struct
rtnl_nh).

So, let's extract some functions to manipulate struct rtnl_nh_encap
directly. Ideally, even for the route's nexthop we will use those to
manipulate the encap.

Ideally we stop using rtnl_route_nh_encap_mpls (and friends) and rather
configure an encapsulation on a route's nexthop by using:

nh = rtnl_nh_encap_alloc()
rtnl_nh_encap_mpls(nh, ...)
rtnl_route_nh_set_encap(rtnh, nh)

Add tests for these new functions and drop the tests for the deprecated
ones.

Signed-off-by: Christoph Paasch <[email protected]>
For better and less error-prone failure handling.

Signed-off-by: Christoph Paasch <[email protected]>
There is support for parsing and populating rtnl_nexthop's encap.
However, not for rtnl_nh's encapsulation.

Refactor this and make it such that the parsing code for both is reused.

Signed-off-by: Christoph Paasch <[email protected]>
@cpaasch-oai
Copy link
Contributor Author

@thom311 - as I fix the backwards compatibility for all callers of nh_encap_parse_msg I opted to not create nh_encap_parse_msg_safe and rather handle the NOSUPPORT directly in nh_encap_parse_msg. LMK if you prefer another approach.

OK, there is also

         if (!lwtunnel_encap_types[e_type].ops->parse_msg)
                  return -NLE_MSGTYPE_NOSUPPORT;

In my opinion, we should never have an encap in lwtunnel_encap_types whose ops has no parse_msg. Because, lwtunnel_encap_types is internal-only we can control what encaps are there. And, I think we can even drop the check here. Yes, we would crash if someone implements an "incorrect" encap, and I think failing loudly is good here.

and

         if (e_type == LWTUNNEL_ENCAP_NONE) {
                  NL_DBG(2, "RTA_ENCAP_TYPE should not be LWTUNNEL_ENCAP_NONE\n");
                  return -NLE_INVAL;
         }

Indeed. I see, iproute2 also handles this case gracefully.

which I think warrant the same handling.

There is also

	if (e_type > LWTUNNEL_ENCAP_MAX) {
		NL_DBG(2, "Unknown RTA_ENCAP_TYPE: %d\n", e_type);

for that one I am adding the graceful handling and just return 0.

A regular "nexthop object" à la `ip nexthop` can have an associated
encapsulation. So, add the code to support that.

Signed-off-by: Christoph Paasch <[email protected]>
@thom311
Copy link
Owner

thom311 commented Aug 27, 2025

In my opinion, we should never have an encap in lwtunnel_encap_types whose ops has no parse_msg. Because, lwtunnel_encap_types is internal-only we can control what encaps are there. And, I think we can even drop the check here. Yes, we would crash if someone implements an "incorrect" encap, and I think failing loudly is good here.

Makes sense. In that case indeed there is no need for a check. A crash (in case of such a bug) is a perfectly fine (deterministic) behavior.

@thom311 thom311 merged commit 6c0c02f into thom311:main Aug 29, 2025
4 checks passed
@thom311
Copy link
Owner

thom311 commented Aug 29, 2025

lgtm. merged.

Thanks @cpaasch-oai for your work.
And thanks @KanjiMonster for caring!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants