[ovs-dev] [PATCH ovn v3] ovn-controller: Add 'local_ip' option to tunnel ports for IPsec case

Mark Michelson mmichels at redhat.com
Mon Mar 15 21:02:08 UTC 2021


LGMT

Acked-by: Mark Michelson <mmichels at redhat.com>

On 2/16/21 6:55 AM, Mark Gray wrote:
> 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 at 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
> 
> diff --git a/controller/chassis.c b/controller/chassis.c
> index 310132d09d2e..9b0a36cf076f 100644
> --- a/controller/chassis.c
> +++ b/controller/chassis.c
> @@ -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;
> diff --git a/controller/encaps.c b/controller/encaps.c
> index 7eac4bb064ac..fc93bf1eeb87 100644
> --- a/controller/encaps.c
> +++ b/controller/encaps.c
> @@ -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;
> diff --git a/tests/automake.mk b/tests/automake.mk
> index df6d0a2a9074..bef40bde07bb 100644
> --- a/tests/automake.mk
> +++ b/tests/automake.mk
> @@ -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 \
> diff --git a/tests/ovn-ipsec.at b/tests/ovn-ipsec.at
> new file mode 100644
> index 000000000000..887281d5be0e
> --- /dev/null
> +++ b/tests/ovn-ipsec.at
> @@ -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
> diff --git a/tests/testsuite.at b/tests/testsuite.at
> index 35908ad3f3fe..ddc3f11d6850 100644
> --- a/tests/testsuite.at
> +++ b/tests/testsuite.at
> @@ -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])
> 



More information about the dev mailing list