@@ -279,6 +279,11 @@ chassis_parse_ovs_config(const struct ovsrec_open_vswitch_table *ovs_table,
return false;
}
+ /* 'ovn-encap-ip' can accept a comma-delimited list of IP addresses instead
+ * of a single IP address. Although this is undocumented, it can be used
+ * to enable certain hardware-offloaded use cases in which a host has
+ * multiple NICs and is assigning SR-IOV VFs to a guest (as logical ports).
+ */
if (!chassis_parse_ovs_encap_ip(encap_ips, &ovs_cfg->encap_ip_set)) {
sset_destroy(&ovs_cfg->encap_type_set);
return false;
@@ -59,6 +59,7 @@ struct tunnel_ctx {
struct ovsdb_idl_txn *ovs_txn;
const struct ovsrec_bridge *br_int;
+ const struct sbrec_chassis *this_chassis;
};
struct chassis_node {
@@ -176,6 +177,28 @@ tunnel_add(struct tunnel_ctx *tc, const struct sbrec_sb_global *sbg,
/* Add auth info if ipsec is enabled. */
if (sbg->ipsec) {
+ const struct sbrec_chassis *this_chassis = tc->this_chassis;
+ const char *local_ip = NULL;
+
+ /* Determine 'ovn-encap-ip' of the local chassis as this will be the
+ * tunnel port's 'local_ip'. We do not support the case in which
+ * 'ovn-encap-ip' holds multiple comma-delimited IP addresses.
+ */
+ for (int i = 0; i < this_chassis->n_encaps; i++) {
+ if (local_ip && strcmp(local_ip, this_chassis->encaps[i]->ip)) {
+ VLOG_ERR("ovn-encap-ip has been configured as a list. This "
+ "is unsupported for IPsec.");
+ /* No need to loop further as we know this condition has been
+ * hit */
+ break;
+ } else {
+ local_ip = this_chassis->encaps[i]->ip;
+ }
+ }
+
+ if (local_ip) {
+ smap_add(&options, "local_ip", local_ip);
+ }
smap_add(&options, "remote_name", new_chassis_id);
}
@@ -310,7 +333,8 @@ encaps_run(struct ovsdb_idl_txn *ovs_idl_txn,
struct tunnel_ctx tc = {
.chassis = SHASH_INITIALIZER(&tc.chassis),
.port_names = SSET_INITIALIZER(&tc.port_names),
- .br_int = br_int
+ .br_int = br_int,
+ .this_chassis = this_chassis
};
tc.ovs_txn = ovs_idl_txn;
@@ -34,7 +34,8 @@ TESTSUITE_AT = \
tests/ovn-performance.at \
tests/ovn-ofctrl-seqno.at \
tests/ovn-ipam.at \
- tests/ovn-lflow-cache.at
+ tests/ovn-lflow-cache.at \
+ tests/ovn-ipsec.at
SYSTEM_KMOD_TESTSUITE_AT = \
tests/system-common-macros.at \
new file mode 100644
@@ -0,0 +1,104 @@
+AT_BANNER([OVN - IPsec])
+
+AT_SETUP([ovn -- ipsec -- basic configuration])
+ovn_start
+
+# Configure the Northbound database
+ovn-nbctl ls-add lsw0
+
+ovn-nbctl lsp-add lsw0 lp1
+ovn-nbctl lsp-set-addresses lp1 "f0:00:00:00:00:01 10.1.1.1"
+
+ovn-nbctl lsp-add lsw0 lp2
+ovn-nbctl lsp-set-addresses lp2 "f0:00:00:00:00:02 10.1.1.2"
+
+net_add n1 # Network to connect hv1 and hv2
+
+# Enable IPsec
+ovn-nbctl set nb_global . ipsec=true
+
+# Create hypervisor hv1 connected to n1
+sim_add hv1
+as hv1
+ovs-vsctl add-br br-phys
+ovn_attach n1 br-phys 192.168.0.1
+ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1
+ovs-vsctl \
+ -- set Open_vSwitch . external-ids:system-id=hv1 \
+ -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
+ -- set Open_vSwitch . external-ids:ovn-encap-ip=192.168.0.1 \
+ -- set Open_vSwitch . other_config:certificate=dummy-cert.pem \
+ -- set Open_vSwitch . other_config:private_key=dummy-privkey.pem \
+ -- set Open_vSwitch . other_config:ca_cert=dummy-cacert.pem
+
+# Create hypervisor hv2 connected to n1
+sim_add hv2
+as hv2
+ovs-vsctl add-br br-phys
+ovn_attach n1 br-phys 192.168.0.2
+ovs-vsctl add-port br-int vif2 -- set Interface vif2 external-ids:iface-id=lp2
+ovs-vsctl \
+ -- set Open_vSwitch . external-ids:system-id=hv2 \
+ -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
+ -- set Open_vSwitch . external-ids:ovn-encap-ip=192.168.0.2 \
+ -- set Open_vSwitch . other_config:certificate=dummy-cert.pem \
+ -- set Open_vSwitch . other_config:private_key=dummy-privkey.pem \
+ -- set Open_vSwitch . other_config:ca_cert=dummy-cacert.pem
+
+AT_CHECK([as hv2 ovs-vsctl get Interface ovn-hv1-0 options:remote_ip | tr -d '"\n'], [0], [192.168.0.1])
+AT_CHECK([as hv2 ovs-vsctl get Interface ovn-hv1-0 options:local_ip | tr -d '"\n'], [0], [192.168.0.2])
+AT_CHECK([as hv2 ovs-vsctl get Interface ovn-hv1-0 options:remote_name | tr -d '\n'], [0], [hv1])
+AT_CHECK([as hv1 ovs-vsctl get Interface ovn-hv2-0 options:remote_ip | tr -d '"\n'], [0], [192.168.0.2])
+AT_CHECK([as hv1 ovs-vsctl get Interface ovn-hv2-0 options:local_ip | tr -d '"\n'], [0], [192.168.0.1])
+AT_CHECK([as hv1 ovs-vsctl get Interface ovn-hv2-0 options:remote_name | tr -d '\n'], [0], [hv2])
+
+AT_CLEANUP
+
+AT_SETUP([ovn -- ipsec -- unsupported multiple ovn-encap-ip values])
+ovn_start
+
+# Configure the Northbound database
+ovn-nbctl ls-add lsw0
+
+ovn-nbctl lsp-add lsw0 lp1
+ovn-nbctl lsp-set-addresses lp1 "f0:00:00:00:00:01 10.1.1.1"
+
+ovn-nbctl lsp-add lsw0 lp2
+ovn-nbctl lsp-set-addresses lp2 "f0:00:00:00:00:02 10.1.1.2"
+
+net_add n1 # Network to connect hv1 and hv2
+
+# Enable IPsec
+ovn-nbctl set nb_global . ipsec=true
+
+# Create hypervisor hv1 connected to n1
+sim_add hv1
+as hv1
+ovs-vsctl add-br br-phys
+ovn_attach n1 br-phys 192.168.0.1
+ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1
+ovs-vsctl \
+ -- set Open_vSwitch . external-ids:system-id=hv1 \
+ -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
+ -- set Open_vSwitch . external-ids:ovn-encap-ip="192.168.0.1, 192.169.0.1" \
+ -- set Open_vSwitch . other_config:certificate=dummy-cert.pem \
+ -- set Open_vSwitch . other_config:private_key=dummy-privkey.pem \
+ -- set Open_vSwitch . other_config:ca_cert=dummy-cacert.pem
+
+# Create hypervisor hv2 connected to n1
+sim_add hv2
+as hv2
+ovs-vsctl add-br br-phys
+ovn_attach n1 br-phys 192.168.0.2
+ovs-vsctl add-port br-int vif2 -- set Interface vif2 external-ids:iface-id=lp2
+ovs-vsctl \
+ -- set Open_vSwitch . external-ids:system-id=hv2 \
+ -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
+ -- set Open_vSwitch . external-ids:ovn-encap-ip="192.168.0.2, 192.169.0.2" \
+ -- set Open_vSwitch . other_config:certificate=dummy-cert.pem \
+ -- set Open_vSwitch . other_config:private_key=dummy-privkey.pem \
+ -- set Open_vSwitch . other_config:ca_cert=dummy-cacert.pem
+
+AT_CHECK([grep "ovn-encap-ip has been configured as a list. This is unsupported for IPsec." hv1/ovn-controller.log],[0], ignore)
+
+AT_CLEANUP
\ No newline at end of file
@@ -36,3 +36,4 @@ m4_include([tests/ovn-controller.at])
m4_include([tests/ovn-controller-vtep.at])
m4_include([tests/ovn-ic.at])
m4_include([tests/checkpatch.at])
+m4_include([tests/ovn-ipsec.at])
If a chassis has multiple interfaces, 'ovn-encap-ip' can be used to specify the IP address of the interface that is used for tunnel traffic. OVN uses that IP address to configure the 'remote_ip' of a tunnel port. OVS tunnel ports also accept 'options:local_ip', which, according to the OVS documentation specifies "the tunnel destination IP that received packets must match. Default is to match all addresses". OVN does not set 'local_ip'. 'ovs-monitor-ipsec' is an OVS daemon that is used to configure and IPsec IKE daemon on the host. In order to correctly specify an IPsec connection, it requires the source and destination IP address of that connection. In the OVN case, as 'local_ip' is not specified, it is unable to infer the IP address of both sides of a tunnel and, therefore, cannot setup an IPsec connection. This patch configures 'local_ip' on tunnel ports when IPsec has been enabled. This allows for OVS/OVN IPsec to work when 'ovn-encap-ip' is not specified as the chassis default gateway interface. This patch also adds some unit tests. The OVS daemon 'ovs-monitor-ipsec' requires a number of options to be configured on OVS tunnel ports in order to function correctly. These unit tests ensure that these options are configured correctly when IPsec has been enabled through the northbound database. Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1924041 Signed-off-by: Mark Gray <mark.d.gray@redhat.com> --- v2: Updated topic filter to "PATCH ovn" v3: Rebased due to 0-day bot warning controller/chassis.c | 5 +++ controller/encaps.c | 26 ++++++++++- tests/automake.mk | 3 +- tests/ovn-ipsec.at | 104 +++++++++++++++++++++++++++++++++++++++++++ tests/testsuite.at | 1 + 5 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 tests/ovn-ipsec.at