From patchwork Sat Jul 20 05:16:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 1962668 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WQw1v1Zc8z1ySl for ; Sat, 20 Jul 2024 15:23:46 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 9E52140012; Sat, 20 Jul 2024 05:23:42 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id Y-OehrxTdJ10; Sat, 20 Jul 2024 05:23:40 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 31E61400D3 Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTPS id 31E61400D3; Sat, 20 Jul 2024 05:23:40 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id EC387C0A97; Sat, 20 Jul 2024 05:23:39 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1ABC4C0A96 for ; Sat, 20 Jul 2024 05:23:39 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 016E240B43 for ; Sat, 20 Jul 2024 05:23:39 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 4wy1VGHKilRq for ; Sat, 20 Jul 2024 05:23:37 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=217.70.178.240; helo=mslow1.mail.gandi.net; envelope-from=hzhou@ovn.org; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp4.osuosl.org 49A3740B42 Authentication-Results: smtp4.osuosl.org; dmarc=none (p=none dis=none) header.from=ovn.org DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 49A3740B42 Received: from mslow1.mail.gandi.net (mslow1.mail.gandi.net [217.70.178.240]) by smtp4.osuosl.org (Postfix) with ESMTPS id 49A3740B42 for ; Sat, 20 Jul 2024 05:23:36 +0000 (UTC) Received: from relay4-d.mail.gandi.net (unknown [217.70.183.196]) by mslow1.mail.gandi.net (Postfix) with ESMTP id DD99DC30CA for ; Sat, 20 Jul 2024 05:17:03 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id 61E93E0002; Sat, 20 Jul 2024 05:16:56 +0000 (UTC) From: Han Zhou To: dev@openvswitch.org Date: Fri, 19 Jul 2024 22:16:48 -0700 Message-Id: <20240720051648.3332549-1-hzhou@ovn.org> X-Mailer: git-send-email 2.38.1 MIME-Version: 1.0 X-GND-Sasl: hzhou@ovn.org Subject: [ovs-dev] [PATCH ovn] ovn-controller: Support ovn-encap-ip-default option. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" When there are multiple encap IPs configured for a chassis, there are situations that any of the IP may be used, e.g. when encap-ip is not configured for a VIF or when the output port of the pipeline is not a VIF but a chassis-redirect port. In such cases, the encap IP used is unpredictable. This patch introduces the ovn-encap-ip-default option, allowing the configuration of a default IP to be used to ensure deterministic encap IP selection in such cases. Signed-off-by: Han Zhou Acked-by: Numan Siddique --- NEWS | 3 +++ controller/binding.c | 13 +++++----- controller/chassis.c | 46 ++++++++++++++++++++++++++++++--- controller/ovn-controller.8.xml | 6 +++++ ovn-sb.xml | 10 +++++++ tests/ovn.at | 37 ++++++++++++++++++++++++-- 6 files changed, 103 insertions(+), 12 deletions(-) diff --git a/NEWS b/NEWS index 3e392ff08b5a..b23977a9316d 100644 --- a/NEWS +++ b/NEWS @@ -38,6 +38,9 @@ Post v24.03.0 ability to disable "VXLAN mode" to extend available tunnel IDs space for datapaths from 4095 to 16711680. For more details see man ovn-nb(5) for mentioned option. + - Add "external_ids:ovn-encap-ip-default" config for ovn-controller to + determine the default encap IP when there are multiple encap IPs + configured. OVN v24.03.0 - 01 Mar 2024 -------------------------- diff --git a/controller/binding.c b/controller/binding.c index b7e7f48749b8..146b03248f14 100644 --- a/controller/binding.c +++ b/controller/binding.c @@ -520,20 +520,21 @@ static struct sbrec_encap * sbrec_get_port_encap(const struct sbrec_chassis *chassis_rec, const struct ovsrec_interface *iface_rec) { - - if (!iface_rec) { + if (chassis_rec->n_encaps < 2) { return NULL; } - const char *encap_ip = smap_get(&iface_rec->external_ids, "encap-ip"); - if (!encap_ip) { - return NULL; + const char *encap_ip = NULL; + if (iface_rec) { + encap_ip = smap_get(&iface_rec->external_ids, "encap-ip"); } struct sbrec_encap *best_encap = NULL; uint32_t best_type = 0; for (int i = 0; i < chassis_rec->n_encaps; i++) { - if (!strcmp(chassis_rec->encaps[i]->ip, encap_ip)) { + if ((encap_ip && !strcmp(chassis_rec->encaps[i]->ip, encap_ip)) || + (!encap_ip && smap_get_bool(&chassis_rec->encaps[i]->options, + "is_default", false))) { uint32_t tun_type = get_tunnel_type(chassis_rec->encaps[i]->type); if (tun_type > best_type) { best_type = tun_type; diff --git a/controller/chassis.c b/controller/chassis.c index 4942ba281d66..7fe38efd1159 100644 --- a/controller/chassis.c +++ b/controller/chassis.c @@ -63,6 +63,8 @@ struct ovs_chassis_cfg { struct sset encap_type_set; /* Set of encap IPs parsed from the 'ovn-encap-ip' external-id. */ struct sset encap_ip_set; + /* Default encap IP when there are two or more encap IPs. Optional. */ + const char *encap_ip_default; /* Interface type list formatted in the OVN-SB Chassis required format. */ struct ds iface_types; /* Is this chassis an interconnection gateway. */ @@ -281,6 +283,7 @@ chassis_parse_ovs_config(const struct ovsrec_open_vswitch_table *ovs_table, const struct ovsrec_bridge *br_int, struct ovs_chassis_cfg *ovs_cfg) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_table_first(ovs_table); @@ -298,7 +301,6 @@ chassis_parse_ovs_config(const struct ovsrec_open_vswitch_table *ovs_table, get_chassis_external_id_value(&cfg->external_ids, chassis_id, "ovn-encap-ip", NULL); if (!encap_type || !encap_ips) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); VLOG_INFO_RL(&rl, "Need to specify an encap type and ip"); return false; } @@ -333,6 +335,16 @@ chassis_parse_ovs_config(const struct ovsrec_open_vswitch_table *ovs_table, * multiple NICs and is assigning SR-IOV VFs to a guest (as logical ports). */ chassis_parse_ovs_encap_ip(encap_ips, &ovs_cfg->encap_ip_set); + const char *encap_ip_default = + get_chassis_external_id_value(&cfg->external_ids, chassis_id, + "ovn-encap-ip-default", NULL); + if (encap_ip_default && + !sset_contains(&ovs_cfg->encap_ip_set, encap_ip_default)) { + VLOG_INFO_RL(&rl, "ovn-encap-ip-default (%s) must be one of the IPs " + "in ovn-encap-ip.", encap_ip_default); + return false; + } + ovs_cfg->encap_ip_default = encap_ip_default; chassis_parse_ovs_iface_types(cfg->iface_types, cfg->n_iface_types, &ovs_cfg->iface_types); @@ -534,6 +546,7 @@ chassis_other_config_changed(const struct ovs_chassis_cfg *ovs_cfg, static bool chassis_tunnels_changed(const struct sset *encap_type_set, const struct sset *encap_ip_set, + const char *encap_ip_default, const char *encap_csum, const struct sbrec_chassis *chassis_rec) { @@ -562,6 +575,19 @@ chassis_tunnels_changed(const struct sset *encap_type_set, changed = true; break; } + + if (smap_get_bool(&chassis_rec->encaps[i]->options, + "is_default", false)) { + if (!encap_ip_default || strcmp(encap_ip_default, + chassis_rec->encaps[i]->ip)) { + changed = true; + break; + } + } else if (encap_ip_default && !strcmp(encap_ip_default, + chassis_rec->encaps[i]->ip)) { + changed = true; + break; + } } if (!changed) { @@ -593,6 +619,7 @@ static struct sbrec_encap ** chassis_build_encaps(struct ovsdb_idl_txn *ovnsb_idl_txn, const struct sset *encap_type_set, const struct sset *encap_ip_set, + const char *encap_ip_default, const char *chassis_id, const char *encap_csum, size_t *n_encap) @@ -613,7 +640,15 @@ chassis_build_encaps(struct ovsdb_idl_txn *ovnsb_idl_txn, sbrec_encap_set_type(encap, encap_type); sbrec_encap_set_ip(encap, encap_ip); - sbrec_encap_set_options(encap, &options); + if (encap_ip_default && !strcmp(encap_ip_default, encap_ip)) { + struct smap _options; + smap_clone(&_options, &options); + smap_add(&_options, "is_default", "true"); + sbrec_encap_set_options(encap, &_options); + smap_destroy(&_options); + } else { + sbrec_encap_set_options(encap, &options); + } sbrec_encap_set_chassis_name(encap, chassis_id); encaps[tunnel_count] = encap; @@ -748,7 +783,9 @@ chassis_update(const struct sbrec_chassis *chassis_rec, /* If any of the encaps should change, update them. */ bool tunnels_changed = chassis_tunnels_changed(&ovs_cfg->encap_type_set, - &ovs_cfg->encap_ip_set, ovs_cfg->encap_csum, + &ovs_cfg->encap_ip_set, + ovs_cfg->encap_ip_default, + ovs_cfg->encap_csum, chassis_rec); if (!tunnels_changed) { return updated; @@ -759,7 +796,8 @@ chassis_update(const struct sbrec_chassis *chassis_rec, encaps = chassis_build_encaps(ovnsb_idl_txn, &ovs_cfg->encap_type_set, - &ovs_cfg->encap_ip_set, chassis_id, + &ovs_cfg->encap_ip_set, + ovs_cfg->encap_ip_default, chassis_id, ovs_cfg->encap_csum, &n_encap); sbrec_chassis_set_encaps(chassis_rec, encaps, n_encap); free(encaps); diff --git a/controller/ovn-controller.8.xml b/controller/ovn-controller.8.xml index 6dad00eb146f..89f08843fcbc 100644 --- a/controller/ovn-controller.8.xml +++ b/controller/ovn-controller.8.xml @@ -204,6 +204,12 @@

+
external_ids:ovn-encap-ip-default
+
+ When ovn-encap-ip contains multiple IPs, this field + indicates the default one. +
+
external_ids:ovn-encap-df_default
indicates the DF flag handling of the encapulation. Set to diff --git a/ovn-sb.xml b/ovn-sb.xml index 73a1be5ed9b8..66d03bd7cdec 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -562,6 +562,16 @@

+ +

+ When there are multiple encaps for a chassis with different IPs, this + option indicates if the encap is the default one that matches the IP in + + column of the Open_vSwitch database's table. +

+
+ The IPv4 address of the encapsulation tunnel endpoint. diff --git a/tests/ovn.at b/tests/ovn.at index adc7cb2c8fc6..8250589814aa 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -30133,8 +30133,21 @@ check_packet_tunnel() { local dst_mac=f0:00:00:00:88:01 # lrp-ls1's MAC local src_ip=$(vif_to_ip vif$src) local dst_ip=$(vif_to_ip vif$dst) - local local_encap_ip=192.168.0.$src - local remote_encap_ip=192.168.0.$dst + + local local_encap_ip + if test -n "$3"; then + local_encap_ip=$3 + else + local_encap_ip=192.168.0.$src + fi + + local remote_encap_ip + if test -n "$4"; then + remote_encap_ip=$4 + else + remote_encap_ip=192.168.0.$dst + fi + local packet=$(fmt_pkt "Ether(dst='${dst_mac}', src='${src_mac}')/ \ IP(dst='${dst_ip}', src='${src_ip}')/ \ ICMP(type=8)") @@ -30151,6 +30164,26 @@ for i in 1 2; do done done +# Set default encap-ip and remove VIF's encap-ip settings. Packets should go +# through default encap-ip. + +for i in 1 2; do + as hv$i + check ovs-vsctl set open . external_ids:ovn-encap-ip-default=192.168.0.${i}2 + + for j in 1 2; do + check ovs-vsctl remove Interface vif$i$j external_ids encap-ip + done +done + +check ovn-nbctl --wait=hv sync + +for i in 1 2; do + for j in 1 2; do + check_packet_tunnel 1$i 2$j 192.168.0.12 192.168.0.22 + done +done + OVN_CLEANUP([hv1],[hv2]) AT_CLEANUP ])