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
[WIP] Add support for gretap/ip6gretap OVS tunnels #261
base: main
Are you sure you want to change the base?
Conversation
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 Brian for this PR! I'm overall happy with the decisions you made and left a few comments inline that should answer most of your questions. The biggest concern is probably the loosening of the local-ip
validation, which should be restricted to the relevant cases.
We will have a final/full review of the PR once testing and documentation is in place, at which time we might also consult Steve about the GRE vs GRETAP wording.
This raises a secondary question about OVS bonds: if a bond detects one of its members being OVS, it then switches its back-end to OVS. However, I didn't see any code to make a bridge containing a now OVS bond to then become OVS.
Well, we might not actually have thought about that case before... I think this is a similar sorting problem to what I described in myparse.c
comment and we probably need to set the parent bridge to use the OVS backend once the child bond changes. We should probably fix this (could even be part of this PR).
Thank you and keep up the good work!
@@ -406,6 +407,33 @@ netplan_netdef_write_ovs(const NetplanState* np_state, const NetplanNetDefinitio | |||
write_ovs_tag_netplan(def->id, type, cmds); | |||
break; | |||
|
|||
case NETPLAN_DEF_TYPE_TUNNEL: | |||
/* Only support gretap and ip6gretap tunnel modes for the time being */ | |||
if (def->tunnel.mode != NETPLAN_TUNNEL_MODE_GRETAP && def->tunnel.mode != NETPLAN_TUNNEL_MODE_IP6GRETAP) { |
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 agree we want to use the GRETAP / IP6GRETAP modes here, if those are the technically correct terms for what is put on the (virtual) wire! (Although OVS calls it just GRE/IP6GRE)
But we probably want to have Steve's opinion on that before we merge this PR.
append_systemd_cmd(cmds, OPENVSWITCH_OVS_VSCTL " --may-exist add-port %s %s -- set interface %s type=%s options:remote_ip=%s", | ||
def->bridge, def->id, def->id, def->tunnel.mode == NETPLAN_TUNNEL_MODE_GRETAP ? "gre" : "ip6gre", def->tunnel.remote_ip) |
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.
Let's add an additional comment here, to avoid an GRE VS GRETAP confusion, ideally referencing some kind of OVS documentation where it is stated that GRE in OVS is actually GRETAP.
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.
Thanks for adding the comment!
nitpick: we have a tiny formatting issue here, as the comment is using tabs instead of spaces. That should be fixed in a later revision.
if (!nd->tunnel.local_ip) | ||
return yaml_error(npp, node, error, "%s: missing 'local' property for tunnel", nd->id); |
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.
Loosening this check is probably fine for most tunnel configurations. But we should not allow people to generate invalid configuration in some cases, so could we please keep this check, but restrict it to the relevant cases?
if (component->type == NETPLAN_DEF_TYPE_TUNNEL && | ||
(component->tunnel.mode == NETPLAN_TUNNEL_MODE_GRETAP || component->tunnel.mode == NETPLAN_TUNNEL_MODE_IP6GRETAP) && | ||
npp->current.netdef->backend == NETPLAN_BACKEND_OVS) { | ||
component->backend = NETPLAN_BACKEND_OVS; |
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.
The netplan net definitions are parsed in the order they are listed in the YAML file.
So if a tunnel is defined before the bridge this code should work. If the bridge is defined first a new netdef will be created via add_missing_node()
, but that will not necessarily have all the tunnel mode settings ready.
So I think we need an additional check in handle_tunnel_mode()
to check if this tunnel is an interface to an OVS bridge and then set the NETPLAN_BACKEND_OVS
accordingly.
We should add test for both cases (bridge first, tunnel first) to make sure this works as expected.
e6cf202
to
0fa575f
Compare
I added an extra comment about the gre->gretap mapping; unfortunately there is no official documentation that references Unfortunately I'm not an expert on all the tunnel types so do you know which actually need the local IP? These are the supported tunnel types and my understanding of whether local IP is needed:
* I'm going off solely https://developers.redhat.com/blog/2019/05/17/an-introduction-to-linux-virtual-interfaces-tunnels#ipip_tunnel which says, for Finally, I'm having second thoughts about my last question. There was already code present to make a bridge OVS-flavored if a member interface was explicitly OVS and I added code to make member interfaces OVS-flavored if the bridge is OVS. It's very possible I'm missing something but what case would hooking |
Thank you! I added a small nitpick inline about that (formatting issue).
What's relevant for netplan is the support in the underlying rendering backends (networkd / NetworkManager), so I've checked the following documentation:
This looks like it is indeed not needed, as we can fallback to
I was thinking about a case where the bridge is defined first, like this:
IIRC this would parse the bridge and create a dummy netdef for
|
0fa575f
to
9d07d56
Compare
Codecov Report
@@ Coverage Diff @@
## main #261 +/- ##
==========================================
- Coverage 99.07% 98.93% -0.15%
==========================================
Files 61 61
Lines 10860 10881 +21
==========================================
+ Hits 10760 10765 +5
- Misses 100 116 +16
Continue to review full report at Codecov.
|
9d07d56
to
a825bd6
Compare
I've hit an issue with the following config: network:
version: 2
renderer: networkd
ethernets:
enp0s3:
dhcp4: yes
enp0s8:
dhcp4: no
addresses:
- 172.16.0.1/24
tunnels:
gre0:
mode: gretap
local: 172.16.0.1
remote: 172.16.0.2
key: 1000
bridges:
br0:
interfaces: ["gre0"]
addresses:
- 10.0.0.1/24
openvswitch: {} Stepping through the code, it looks like the tunnel is defined with backend I thought about trying to call Given that the tunnel has no linkage to the bridge at the time the tunnel is defined and the bridge has no stateful reference to its members, I'm a bit stuck on how to proceed. Should I add a field to the |
Interestingly, that test case seems to recognize |
It makes me feel slightly better that you're also perplexed by this issue. Let me know if you need me to do anything! |
Hey @Caligatio, I finally found some time to investigate the issue and understand what is going on now:
This also explains why it works if we move the So instead of trying to get a reference during the parsing of individual interfaces, we could make use of the diff --git a/src/parse.c b/src/parse.c
index d281a7f..b0d570c 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -1215,12 +1215,6 @@ handle_bridge_interfaces(NetplanParser* npp, yaml_node_t* node, const void* data
g_debug("%s: Bridge contains openvswitch interface, choosing OVS backend", npp->current.netdef->id);
npp->current.netdef->backend = NETPLAN_BACKEND_OVS;
}
- /* If the bridge has a OVS backend then any gretap or ip6gretap tunnels attached to the bridge must also be OVS */
- if (component->type == NETPLAN_DEF_TYPE_TUNNEL &&
- (component->tunnel.mode == NETPLAN_TUNNEL_MODE_GRETAP || component->tunnel.mode == NETPLAN_TUNNEL_MODE_IP6GRETAP) &&
- npp->current.netdef->backend == NETPLAN_BACKEND_OVS) {
- component->backend = NETPLAN_BACKEND_OVS;
- }
}
}
@@ -2758,6 +2752,17 @@ netplan_parser_load_yaml(NetplanParser* npp, const char* filename, GError** erro
static gboolean
finish_iterator(const NetplanParser* npp, NetplanNetDefinition* nd, GError **error)
{
+ /* If a bridge has a OVS backend then any gretap or ip6gretap tunnels attached to the bridge must also be OVS */
+ if (nd->type == NETPLAN_DEF_TYPE_TUNNEL && nd->bridge &&
+ (nd->tunnel.mode == NETPLAN_TUNNEL_MODE_GRETAP || nd->tunnel.mode == NETPLAN_TUNNEL_MODE_IP6GRETAP)) {
+ char *parent = nd->bridge;
+ NetplanNetDefinition *parent_nd = g_hash_table_lookup(npp->parsed_defs, parent);
+ if (parent_nd && parent_nd->backend == NETPLAN_BACKEND_OVS) {
+ g_debug("%s: setting backend to OVS implicitly (interface of %s)", nd->id, parent);
+ nd->backend = NETPLAN_BACKEND_OVS;
+ }
+ }
+
/* Take more steps to make sure we always have a backend set for netdefs */
if (nd->backend == NETPLAN_BACKEND_NONE) {
nd->backend = get_default_backend_for_type(npp->global_backend, nd->type); |
@slyon Any progress on getting this working? Thanks! |
I'm not sure if @Caligatio is still interested in driving this forward? If not it would probably up for grabs, like for anybody else to continue working on this. I gave some review comments a while ago above. |
Sorry for the delay in responding but I'm in the midst of an international move :) I unfortunately am no longer in a position to work on this so it would be great if someone could pick this up where I left off. |
Description
This adds support for
gretap
andip6gretap
Open vSwitch (OVS) tunnels to netplan. I'm hoping to get help/feedback on a few questions:gre
tunnels. However, in the semantics of netplan, it is actually agretap
tunnel (i.e. it's putting layer 2 packets through a GRE tunnel). I went with calling thesegretap
/ip6gretap
tunnels as I feel it's technically correct but I also think this is going to cause confusion. Thoughts?local_ip
is a required YAML key but it's really optional for most tunnels. Is it OK to remove the required check on it? I'm happy to tweak the affected tests.gretap
/ip6gretap
tunnels inherit being OVS controlled. I don't have a firm understanding on the order in which interfaces are parsed so am unsure if this method works every time or is dependent on interface order.Once/if people are happy with my changes, I'll tack on another commit with tests.
Checklist
make check
successfully.make check-coverage
).