-
Notifications
You must be signed in to change notification settings - Fork 201
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
networkmanager: add support for "routing-policy" (LP: #2086544) #526
Conversation
f7e1f21
to
cbc9908
Compare
Are the two checks that are failing broken? Guidance here would be appreciated. |
Yes, those failures seem to be unrelated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much for your contribution to Netplan! This is a valuable change and much appreciated.
I especially like the fact that you adopted the corresponding integration tests, so we can be sure it works on real systems!
For future work, may I suggest implementing the other way around, too? E.g. update src/parse-nm.c
(similar to the existing parse_routes()
function), to read a NM keyfile, which should then be picked up automatically by src/netplan.c
to emit corresponding YAML. But this could be done in a follow-up PR, does not need to be part of this PR.
I've been looking at that. Do you have any thoughts about how best to handle NetworkManager routing-rules that contain elements not supported by netplan? We can obviously skip them and they will be imported as pass-through NetworkManager options. The problem is when there are multiple routing-ruleX entries and some can be represented natively by the netplan yaml and some cannot. In that case, I suspect we cannot just naively convert some of the rules to native netplan and allow the others to be recorded as pass-through entries because the NetworkManager rules are numbered, like "routing-rule2". If we record some of the rules in native netplan and some as pass-through rules and then generate the NetworkManager configuration, then new NetworkManager rules will be emitted starting with "routing-rule1", "routing-rule2", potentially clobbering pass-through rules with the same numbering. For example, consider a NetworkManager keyfile containing:
routing-rule2 would be imported and recorded natively as a netplan routing-policy entry while routing-rule1 would be recorded as a pass-through rule since it contains fields not supported by netplan. When the NetworkManager config is then generated from the netplan yaml, it would emit a "routing-rule1" from its own "routing-policy" and then pass through the original "routing-rule1" from the pass-through section. The easiest solution may be to just have an all-or-none policy when importing the NetworkManager routing-ruleXs. Otherwise it seems like we'd need to be aware of any routing-ruleXs in the pass-through section and take them into account when generating the NetworkManager config. Thoughts? |
Yes, this is a very valid concern!
I think one relatively easy approach could be parse all the routing-ruleXs into native Netplan routing-policy, logging a warning when we cannot map any of them. But then do not clear any of them from the keyfile/passthrough (don't call Then, in PS: As mentioned above, please consider this additional work as a non-blocking request, which can easily be delivered in a follow-up PR in the future. |
cbc9908
to
cc5d82d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much for addressing my concerns. This is now ready to be merged!
@drafnel Do you want to add anything on top of it (from the "future work" discussion), or shall we get this merged, first?
I was going to ask how you wanted to do that. I've implemented your suggestion to emit a warning when priority is not set for a rule, which I think can safely be added on top. I'll push this out later today.
The other change, to parse the NetworkManager config, will require more consideration.
…On November 13, 2024 4:12:30 AM CST, "Lukas Märdian" ***@***.***> wrote:
@slyon approved this pull request.
Thank you very much for addressing my concerns. This is now ready to be merged!
@drafnel Do you want to add anything on top of it (from the "future work" discussion), or shall we get this merged, first?
--
Reply to this email directly or view it on GitHub:
#526 (review)
You are receiving this because you were mentioned.
Message ID: ***@***.***>
|
Were you thinking of doing this check in parse_nm.c:read_passthrough()? It doesn't look like the Netplan object is available within that function to be able to count the number of native routing-policy rules. It seems like it would be fine to do this in the same function that parses the rules (i.e. parse_ip_rules()). But, how concerned are you about having two versions of the routing policy configuration in the same file and the possibility of someone editing the netplan yaml by hand? It sounds like that's what you were suggesting if we parse each routing-ruleX, if possible, into a native routing-policy config and keep all of the routing-ruleX entries as pass-through configs when we fail to parse any of the routing-ruleXs into routing-policy configs. So we could end up with something like:
I had thought that a reasonable approach, based on your original suggestion, might be to clear each passthrough rule as long as we've been able to successfully convert the routing-ruleX into a routing-policy rule, but once we encounter a rule that cannot be converted, stop clearing the routing-ruleXs. We still convert as many routing-ruleXs as possible into routing-policy rules, but the ones that are converted after the one we failed to parse will be overwritten by the pass-through rules. For example, the above snippet would become something like:
i.e. since routing-rule1 was successfully parsed, it was cleared. The routing-rule2 would fail to convert since we don't support 'iif' etc. so then we stop clearing the routing-ruleXs. routing-rule3 is successfully converted to a routing-policy, but we still keep the routing-rule3. When this is converted back to NetworkManager key file, then the first routing-policy would become routing-rule1, routing-rule2 would override the second routing-policy (which was derived from routing-rule3), and routing-rule3 would pass through. But that seems a little fragile and confusing to me to mix the two configuration forms like this. Is there actually any value in writing the routing-policy rules if they'll be overridden or supplemented by the routing-ruleX rules? I don't have enough experience with netplan to feel strongly about this either way. Or should we just take an all-or-none approach and refrain from emitting any routing-policy entries if we encounter a routing-ruleX that we cannot convert? |
NetworkManager supports ip rules via the "routing-ruleX" field. Let's teach the networkmanager backend to emit "routing-ruleX" entries for each "routing-policy" entry in the netplan yaml. Update the tests for the new behavior and add additional tests to exercise the new code paths.
Since the check of whether r->table == nd->vrf_table has already failed in the initial 'if' conditional, r->table is necessarily != nd->vrf_table. It is not necessary to explicitly check for this state in the 'else if' conditional. Let's not.
The iproute2 guidance says "Each rule should have an explicitly set unique priority value", and further warns: For historical reasons ip rule add does not require any priority value and allows the priority value to be non-unique. If the user had not supplied a priority value then one was assigned by the kernel. If the user requested creating a rule with a priority value which already existed then the kernel did not reject the request and added the new rule before all old rules of the same priority. This is a mistake in the current design, nothing more. It should be fixed by the time you read this so please do not rely on this feature. You should always use explicit priorities when creating rules. So let's inspect each routing-policy entry and emit a warning if a priority has not been specified. ref. http://www.policyrouting.org/iproute2.doc.html#ss9.6.1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was going to ask how you wanted to do that. I've implemented your suggestion to emit a warning when priority is not set for a rule, which I think can safely be added on top. I'll push this out later today.
ACK, thanks! LGTM.
I took the freedom to rebase your branch on top of origin/main
, added curly braces for the new policy
validation warning (as that's what we want to do everywhere these days), and prefixed two of the commit messages with ATTN:
so that we can consider the stricter schema parsing/validation logic when backporting those changes in the distro.
All CI is now green as well (cf. #528). So let's get this merged!
The other change, to parse the NetworkManager config, will require more consideration.
Let's move this work to an independent PR. More on this in a follow-up comment.
bb0f8a7
to
e0c8801
Compare
@@ -523,10 +523,13 @@ adopt_and_validate_vrf_routes(__unused const NetplanParser *npp, GHashTable *net | |||
if (nd->ip_rules) { | |||
for (size_t i = 0; i < nd->ip_rules->len; i++) { | |||
NetplanIPRule* r = g_array_index(nd->ip_rules, NetplanIPRule*, i); | |||
if (r->priority == NETPLAN_IP_RULE_PRIO_UNSPEC) { | |||
g_warning("%s: No priority specified for routing-policy %zu", nd->id, i); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note (non-blocking): I just see (after merging) that this only triggers for NETPLAN_DEF_TYPE_VRF
NetDefs. We might want to have it for all interface types, eventually.
My initial idea was to handle it in So yes, I agree it should be done in a new note (non-blocking): Looking into
Right. In the end, we want to have all information (as much as possible) available in the defined native Netplan schema, so that external consumers that try to query the configuration (e.g. using
thought:
I agree, it's confusing. As stated above, the value would be for consumers to query the Netplan config state in a programmatic way (e.g. via So, how can we solve this? What about this approach, all implemented inside a single, new
This should solve the duplicated entries in Netplan YAML issue and the issue of "routing-policy" entries not being authorative.
We still have one problem, though: What happens if somebody manually modifies the Netplan YAML config, adding a 3rd routing-policy rule? – It would be in conflict with "routing-rule3" from passthrough. It's an edge case, but we should still handle it nicely and make users aware of it. To mitigate that, we could modify @drafnel WDYT? |
Yeah, probably.
Yeah, I think we have to bite the bullet and go ahead and rewrite the rules.
Or if a rule is deleted, leaving a gap between the numbering of the routing-ruleXs that will be generated in the NetworkManager config from the routing-policy rules and the numbering of the passthrough rules.
A warning, at a minimum, seems appropriate. |
Description
NetworkManager supports ip rules via the "routing-ruleX" field. Let's teach the networkmanager backend to emit "routing-ruleX" entries for each "routing-policy" entry in the netplan yaml.
For example, the following netplan configuration snippet:
..should generate something like the following in the NetworkManager configuration:
Checklist
make check
successfully.make check-coverage
).