Skip to content

Commit

Permalink
ovn-controller: Support VIF-based local encap IPs selection.
Browse files Browse the repository at this point in the history
Commit dd527a2 partially supported multiple encap IPs. It supported
remote encap IP selection based on the destination VIF's encap_ip
configuration. This patch adds the support for selecting local encap IP
based on the source VIF's encap_ip configuration.

Co-authored-by: Lei Huang <leih@nvidia.com>
Signed-off-by: Lei Huang <leih@nvidia.com>
Signed-off-by: Han Zhou <hzhou@ovn.org>
Acked-by: Ales Musil <amusil@redhat.com>
  • Loading branch information
hzhou8 and Lei Huang committed Jan 30, 2024
1 parent 41eefcb commit 17b6a12
Show file tree
Hide file tree
Showing 11 changed files with 240 additions and 54 deletions.
3 changes: 3 additions & 0 deletions NEWS
Expand Up @@ -15,6 +15,9 @@ Post v23.09.0
- A new LSP option "enable_router_port_acl" has been added to enable
conntrack for the router port whose peer is l3dgw_port if set it true.
- Enable PMTU discovery on geneve/vxlan tunnels for E/W traffic.
- Support selecting encapsulation IP based on the source/destination VIF's
settting. See ovn-controller(8) 'external_ids:ovn-encap-ip' for more
details.

OVN v23.09.0 - 15 Sep 2023
--------------------------
Expand Down
2 changes: 1 addition & 1 deletion controller/chassis.c
Expand Up @@ -61,7 +61,7 @@ struct ovs_chassis_cfg {

/* Set of encap types parsed from the 'ovn-encap-type' external-id. */
struct sset encap_type_set;
/* Set of encap IPs parsed from the 'ovn-encap-type' external-id. */
/* Set of encap IPs parsed from the 'ovn-encap-ip' external-id. */
struct sset encap_ip_set;
/* Interface type list formatted in the OVN-SB Chassis required format. */
struct ds iface_types;
Expand Down
2 changes: 1 addition & 1 deletion controller/local_data.c
Expand Up @@ -528,7 +528,7 @@ chassis_tunnels_destroy(struct hmap *chassis_tunnels)
*/
struct chassis_tunnel *
chassis_tunnel_find(const struct hmap *chassis_tunnels, const char *chassis_id,
char *remote_encap_ip, char *local_encap_ip)
char *remote_encap_ip, const char *local_encap_ip)
{
/*
* If the specific encap_ip is given, look for the chassisid_ip entry,
Expand Down
2 changes: 1 addition & 1 deletion controller/local_data.h
Expand Up @@ -154,7 +154,7 @@ bool local_nonvif_data_handle_ovs_iface_changes(
struct chassis_tunnel *chassis_tunnel_find(const struct hmap *chassis_tunnels,
const char *chassis_id,
char *remote_encap_ip,
char *local_encap_ip);
const char *local_encap_ip);

bool get_chassis_tunnel_ofport(const struct hmap *chassis_tunnels,
const char *chassis_name,
Expand Down
30 changes: 26 additions & 4 deletions controller/ovn-controller.8.xml
Expand Up @@ -176,10 +176,32 @@

<dt><code>external_ids:ovn-encap-ip</code></dt>
<dd>
The IP address that a chassis should use to connect to this node
using encapsulation types specified by
<code>external_ids:ovn-encap-type</code>. Multiple encapsulation IPs
may be specified with a comma-separated list.
<p>
The IP address that a chassis should use to connect to this node
using encapsulation types specified by
<code>external_ids:ovn-encap-type</code>. Multiple encapsulation IPs
may be specified with a comma-separated list.
</p>
<p>
In scenarios where multiple encapsulation IPs are present, distinct
tunnels are established for each remote chassis. These tunnels are
differentiated by setting unique <code>options:local_ip</code> and
<code>options:remote_ip</code> values in the tunnel interface. When
transmitting a packet to a remote chassis, the selection of local_ip
is guided by the <code>Interface:external_ids:encap-ip</code> from
the local OVSDB, corresponding to the VIF originating the packet, if
specified. The <code>Interface:external_ids:encap-ip</code> setting
of the VIF is also populated to the <code>Port_Binding</code>
table in the OVN SB database via the <code>encap</code> column.
Consequently, when a remote chassis needs to send a packet to a
port-binding associated with this VIF, it utilizes the tunnel with
the appropriate <code>options:remote_ip</code> that matches the
<code>ip</code> in <code>Port_Binding:encap</code>. This mechanism
is particularly beneficial for chassis with multiple physical
interfaces designated for tunneling, where each interface is
optimized for handling specific traffic associated with particular
VIFs.
</p>
</dd>

<dt><code>external_ids:ovn-encap-df_default</code></dt>
Expand Down
46 changes: 46 additions & 0 deletions controller/ovn-controller.c
Expand Up @@ -4544,6 +4544,30 @@ struct ed_type_pflow_output {
struct physical_debug debug;
};

static void
parse_encap_ips(const struct ovsrec_open_vswitch_table *ovs_table,
size_t *n_encap_ips, const char * **encap_ips)
{
const struct ovsrec_open_vswitch *cfg =
ovsrec_open_vswitch_table_first(ovs_table);
const char *chassis_id = get_ovs_chassis_id(ovs_table);
const char *encap_ips_str =
get_chassis_external_id_value(&cfg->external_ids, chassis_id,
"ovn-encap-ip", NULL);
struct sset encap_ip_set;
sset_from_delimited_string(&encap_ip_set, encap_ips_str, ",");

/* Sort the ips so that their index is deterministic. */
*encap_ips = sset_sort(&encap_ip_set);

/* Copy the strings so that we can destroy the sset. */
for (size_t i = 0; (*encap_ips)[i]; i++) {
(*encap_ips)[i] = xstrdup((*encap_ips)[i]);
}
*n_encap_ips = sset_count(&encap_ip_set);
sset_destroy(&encap_ip_set);
}

static void init_physical_ctx(struct engine_node *node,
struct ed_type_runtime_data *rt_data,
struct ed_type_non_vif_data *non_vif_data,
Expand Down Expand Up @@ -4595,6 +4619,7 @@ static void init_physical_ctx(struct engine_node *node,
engine_get_input_data("ct_zones", node);
struct simap *ct_zones = &ct_zones_data->current;

parse_encap_ips(ovs_table, &p_ctx->n_encap_ips, &p_ctx->encap_ips);
p_ctx->sbrec_port_binding_by_name = sbrec_port_binding_by_name;
p_ctx->sbrec_port_binding_by_datapath = sbrec_port_binding_by_datapath;
p_ctx->port_binding_table = port_binding_table;
Expand All @@ -4618,6 +4643,15 @@ static void init_physical_ctx(struct engine_node *node,
pflow_output_get_debug(node, &p_ctx->debug);
}

static void
destroy_physical_ctx(struct physical_ctx *p_ctx)
{
for (size_t i = 0; i < p_ctx->n_encap_ips; i++) {
free((char *)(p_ctx->encap_ips[i]));
}
free(p_ctx->encap_ips);
}

static void *
en_pflow_output_init(struct engine_node *node OVS_UNUSED,
struct engine_arg *arg OVS_UNUSED)
Expand Down Expand Up @@ -4654,6 +4688,7 @@ en_pflow_output_run(struct engine_node *node, void *data)
struct physical_ctx p_ctx;
init_physical_ctx(node, rt_data, non_vif_data, &p_ctx);
physical_run(&p_ctx, pflow_table);
destroy_physical_ctx(&p_ctx);

engine_set_node_state(node, EN_UPDATED);
}
Expand Down Expand Up @@ -4698,6 +4733,7 @@ pflow_output_if_status_mgr_handler(struct engine_node *node,
bool removed = sbrec_port_binding_is_deleted(binding);
if (!physical_handle_flows_for_lport(binding, removed, &p_ctx,
&pfo->flow_table)) {
destroy_physical_ctx(&p_ctx);
return false;
}
}
Expand All @@ -4707,11 +4743,13 @@ pflow_output_if_status_mgr_handler(struct engine_node *node,
bool removed = sbrec_port_binding_is_deleted(pb);
if (!physical_handle_flows_for_lport(pb, removed, &p_ctx,
&pfo->flow_table)) {
destroy_physical_ctx(&p_ctx);
return false;
}
}
engine_set_node_state(node, EN_UPDATED);
}
destroy_physical_ctx(&p_ctx);
return true;
}

Expand All @@ -4738,11 +4776,13 @@ pflow_output_sb_port_binding_handler(struct engine_node *node,
bool removed = sbrec_port_binding_is_deleted(pb);
if (!physical_handle_flows_for_lport(pb, removed, &p_ctx,
&pfo->flow_table)) {
destroy_physical_ctx(&p_ctx);
return false;
}
}

engine_set_node_state(node, EN_UPDATED);
destroy_physical_ctx(&p_ctx);
return true;
}

Expand All @@ -4762,6 +4802,7 @@ pflow_output_sb_multicast_group_handler(struct engine_node *node, void *data)
physical_handle_mc_group_changes(&p_ctx, &pfo->flow_table);

engine_set_node_state(node, EN_UPDATED);
destroy_physical_ctx(&p_ctx);
return true;
}

Expand Down Expand Up @@ -4794,6 +4835,7 @@ pflow_output_runtime_data_handler(struct engine_node *node, void *data)
if (tdp->tracked_type != TRACKED_RESOURCE_UPDATED) {
/* Fall back to full recompute when a local datapath
* is added or deleted. */
destroy_physical_ctx(&p_ctx);
return false;
}

Expand All @@ -4804,12 +4846,14 @@ pflow_output_runtime_data_handler(struct engine_node *node, void *data)
lport->tracked_type == TRACKED_RESOURCE_REMOVED ? true: false;
if (!physical_handle_flows_for_lport(lport->pb, removed, &p_ctx,
&pfo->flow_table)) {
destroy_physical_ctx(&p_ctx);
return false;
}
}
}

engine_set_node_state(node, EN_UPDATED);
destroy_physical_ctx(&p_ctx);
return true;
}

Expand Down Expand Up @@ -4866,12 +4910,14 @@ pflow_output_activated_ports_handler(struct engine_node *node, void *data)
if (pb) {
if (!physical_handle_flows_for_lport(pb, false, &p_ctx,
&pfo->flow_table)) {
destroy_physical_ctx(&p_ctx);
return false;
}
tag_port_as_activated_in_engine(pp);
}
}
engine_set_node_state(node, EN_UPDATED);
destroy_physical_ctx(&p_ctx);
return true;
}

Expand Down

0 comments on commit 17b6a12

Please sign in to comment.