@@ -506,23 +506,6 @@ update_active_pb_ras_pd(const struct sbrec_port_binding *pb,
}
}
-/* Corresponds to each Port_Binding.type. */
-enum en_lport_type {
- LP_UNKNOWN,
- LP_VIF,
- LP_CONTAINER,
- LP_PATCH,
- LP_L3GATEWAY,
- LP_LOCALNET,
- LP_LOCALPORT,
- LP_L2GATEWAY,
- LP_VTEP,
- LP_CHASSISREDIRECT,
- LP_VIRTUAL,
- LP_EXTERNAL,
- LP_REMOTE
-};
-
/* Local bindings. binding.c module binds the logical port (represented by
* Port_Binding rows) and sets the 'chassis' column when it sees the
* OVS interface row (of type "" or "internal") with the
@@ -576,7 +559,7 @@ static struct local_binding *local_binding_create(
static void local_binding_add(struct shash *local_bindings,
struct local_binding *);
static struct local_binding *local_binding_find(
- struct shash *local_bindings, const char *name);
+ const struct shash *local_bindings, const char *name);
static void local_binding_destroy(struct local_binding *,
struct shash *binding_lports);
static void local_binding_delete(struct local_binding *,
@@ -661,7 +644,8 @@ local_binding_data_destroy(struct local_binding_data *lbinding_data)
}
const struct sbrec_port_binding *
-local_binding_get_primary_pb(struct shash *local_bindings, const char *pb_name)
+local_binding_get_primary_pb(struct shash *local_bindings,
+ const char *pb_name)
{
struct local_binding *lbinding =
local_binding_find(local_bindings, pb_name);
@@ -670,6 +654,19 @@ local_binding_get_primary_pb(struct shash *local_bindings, const char *pb_name)
return b_lport ? b_lport->pb : NULL;
}
+ofp_port_t
+local_binding_get_lport_ofport(const struct shash *local_bindings,
+ const char *pb_name)
+{
+ struct local_binding *lbinding =
+ local_binding_find(local_bindings, pb_name);
+ struct binding_lport *b_lport =
+ local_binding_get_primary_or_localport_lport(lbinding);
+
+ return (b_lport && lbinding->iface && lbinding->iface->n_ofport) ?
+ u16_to_ofp(lbinding->iface->ofport[0]) : 0;
+}
+
bool
local_binding_is_up(struct shash *local_bindings, const char *pb_name)
{
@@ -836,7 +833,7 @@ is_lport_vif(const struct sbrec_port_binding *pb)
return !pb->type[0];
}
-static enum en_lport_type
+enum en_lport_type
get_lport_type(const struct sbrec_port_binding *pb)
{
if (is_lport_vif(pb)) {
@@ -2479,7 +2476,7 @@ local_binding_create(const char *name, const struct ovsrec_interface *iface)
}
static struct local_binding *
-local_binding_find(struct shash *local_bindings, const char *name)
+local_binding_find(const struct shash *local_bindings, const char *name)
{
return shash_find_data(local_bindings, name);
}
@@ -114,6 +114,9 @@ void local_binding_data_destroy(struct local_binding_data *);
const struct sbrec_port_binding *local_binding_get_primary_pb(
struct shash *local_bindings, const char *pb_name);
+ofp_port_t local_binding_get_lport_ofport(const struct shash *local_bindings,
+ const char *pb_name);
+
bool local_binding_is_up(struct shash *local_bindings, const char *pb_name);
bool local_binding_is_down(struct shash *local_bindings, const char *pb_name);
void local_binding_set_up(struct shash *local_bindings, const char *pb_name,
@@ -134,4 +137,24 @@ bool binding_handle_port_binding_changes(struct binding_ctx_in *,
void binding_tracked_dp_destroy(struct hmap *tracked_datapaths);
void binding_dump_local_bindings(struct local_binding_data *, struct ds *);
+
+/* Corresponds to each Port_Binding.type. */
+enum en_lport_type {
+ LP_UNKNOWN,
+ LP_VIF,
+ LP_CONTAINER,
+ LP_PATCH,
+ LP_L3GATEWAY,
+ LP_LOCALNET,
+ LP_LOCALPORT,
+ LP_L2GATEWAY,
+ LP_VTEP,
+ LP_CHASSISREDIRECT,
+ LP_VIRTUAL,
+ LP_EXTERNAL,
+ LP_REMOTE
+};
+
+enum en_lport_type get_lport_type(const struct sbrec_port_binding *);
+
#endif /* controller/binding.h */
@@ -58,6 +58,7 @@ struct lookup_port_aux {
const struct sbrec_datapath_binding *dp;
const struct sbrec_logical_flow *lflow;
struct lflow_resource_ref *lfrr;
+ const struct hmap *chassis_tunnels;
};
struct condition_aux {
@@ -145,7 +146,8 @@ tunnel_ofport_cb(const void *aux_, const char *port_name, ofp_port_t *ofport)
return false;
}
- if (!get_tunnel_ofport(pb->chassis->name, NULL, ofport)) {
+ if (!get_chassis_tunnel_ofport(aux->chassis_tunnels, pb->chassis->name,
+ NULL, ofport)) {
return false;
}
@@ -612,6 +614,7 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow,
.dp = dp,
.lflow = lflow,
.lfrr = l_ctx_out->lfrr,
+ .chassis_tunnels = l_ctx_in->chassis_tunnels,
};
/* Parse any meter to be used if this flow should punt packets to
@@ -147,6 +147,7 @@ struct lflow_ctx_in {
const struct shash *port_groups;
const struct sset *active_tunnels;
const struct sset *related_lport_ids;
+ const struct hmap *chassis_tunnels;
};
struct lflow_ctx_out {
@@ -18,10 +18,14 @@
/* OVS includes. */
#include "include/openvswitch/json.h"
#include "lib/hmapx.h"
+#include "lib/flow.h"
#include "lib/util.h"
+#include "lib/vswitch-idl.h"
#include "openvswitch/vlog.h"
/* OVN includes. */
+#include "encaps.h"
+#include "lport.h"
#include "lib/ovn-util.h"
#include "lib/ovn-sb-idl.h"
#include "local_data.h"
@@ -268,6 +272,166 @@ tracked_datapaths_destroy(struct hmap *tracked_datapaths)
hmap_destroy(tracked_datapaths);
}
+/* Iterates the br_int ports and build the simap of patch to ofports
+ * and chassis tunnels. */
+void
+local_nonvif_data_run(const struct ovsrec_bridge *br_int,
+ const struct sbrec_chassis *chassis_rec,
+ struct simap *patch_ofports,
+ struct hmap *chassis_tunnels)
+{
+ for (int i = 0; i < br_int->n_ports; i++) {
+ const struct ovsrec_port *port_rec = br_int->ports[i];
+ if (!strcmp(port_rec->name, br_int->name)) {
+ continue;
+ }
+
+ const char *tunnel_id = smap_get(&port_rec->external_ids,
+ "ovn-chassis-id");
+ if (tunnel_id && encaps_tunnel_id_match(tunnel_id,
+ chassis_rec->name,
+ NULL)) {
+ continue;
+ }
+
+ const char *localnet = smap_get(&port_rec->external_ids,
+ "ovn-localnet-port");
+ const char *l2gateway = smap_get(&port_rec->external_ids,
+ "ovn-l2gateway-port");
+
+ for (int j = 0; j < port_rec->n_interfaces; j++) {
+ const struct ovsrec_interface *iface_rec = port_rec->interfaces[j];
+
+ /* Get OpenFlow port number. */
+ if (!iface_rec->n_ofport) {
+ continue;
+ }
+ int64_t ofport = iface_rec->ofport[0];
+ if (ofport < 1 || ofport > ofp_to_u16(OFPP_MAX)) {
+ continue;
+ }
+
+ bool is_patch = !strcmp(iface_rec->type, "patch");
+ if (is_patch && localnet) {
+ simap_put(patch_ofports, localnet, ofport);
+ break;
+ } else if (is_patch && l2gateway) {
+ /* L2 gateway patch ports can be handled just like VIFs. */
+ simap_put(patch_ofports, l2gateway, ofport);
+ break;
+ } else if (tunnel_id) {
+ enum chassis_tunnel_type tunnel_type;
+ if (!strcmp(iface_rec->type, "geneve")) {
+ tunnel_type = GENEVE;
+ } else if (!strcmp(iface_rec->type, "stt")) {
+ tunnel_type = STT;
+ } else if (!strcmp(iface_rec->type, "vxlan")) {
+ tunnel_type = VXLAN;
+ } else {
+ continue;
+ }
+
+ /* We split the tunnel_id to get the chassis-id
+ * and hash the tunnel list on the chassis-id. The
+ * reason to use the chassis-id alone is because
+ * there might be cases (multicast, gateway chassis)
+ * where we need to tunnel to the chassis, but won't
+ * have the encap-ip specifically.
+ */
+ char *hash_id = NULL;
+ char *ip = NULL;
+
+ if (!encaps_tunnel_id_parse(tunnel_id, &hash_id, &ip)) {
+ continue;
+ }
+ struct chassis_tunnel *tun = xmalloc(sizeof *tun);
+ hmap_insert(chassis_tunnels, &tun->hmap_node,
+ hash_string(hash_id, 0));
+ tun->chassis_id = xstrdup(tunnel_id);
+ tun->ofport = u16_to_ofp(ofport);
+ tun->type = tunnel_type;
+
+ free(hash_id);
+ free(ip);
+ break;
+ }
+ }
+ }
+}
+
+bool
+local_nonvif_data_handle_ovs_iface_changes(
+ const struct ovsrec_interface_table *iface_table)
+{
+ const struct ovsrec_interface *iface_rec;
+ OVSREC_INTERFACE_TABLE_FOR_EACH_TRACKED (iface_rec, iface_table) {
+ if (!strcmp(iface_rec->type, "geneve") ||
+ !strcmp(iface_rec->type, "patch") ||
+ !strcmp(iface_rec->type, "vxlan") ||
+ !strcmp(iface_rec->type, "stt")) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+get_chassis_tunnel_ofport(const struct hmap *chassis_tunnels,
+ const char *chassis_name, char *encap_ip,
+ ofp_port_t *ofport)
+{
+ struct chassis_tunnel *tun = NULL;
+ tun = chassis_tunnel_find(chassis_tunnels, chassis_name, encap_ip);
+ if (!tun) {
+ return false;
+ }
+
+ *ofport = tun->ofport;
+ return true;
+}
+
+
+void
+chassis_tunnels_destroy(struct hmap *chassis_tunnels)
+{
+ struct chassis_tunnel *tun;
+ HMAP_FOR_EACH_POP (tun, hmap_node, chassis_tunnels) {
+ free(tun->chassis_id);
+ free(tun);
+ }
+ hmap_destroy(chassis_tunnels);
+}
+
+
+/*
+ * This function looks up the list of tunnel ports (provided by
+ * ovn-chassis-id ports) and returns the tunnel for the given chassid-id and
+ * encap-ip. The ovn-chassis-id is formed using the chassis-id and encap-ip.
+ * The list is hashed using the chassis-id. If the encap-ip is not specified,
+ * it means we'll just return a tunnel for that chassis-id, i.e. we just check
+ * for chassis-id and if there is a match, we'll return the tunnel.
+ * If encap-ip is also provided we use both chassis-id and encap-ip to do
+ * a more specific lookup.
+ */
+struct chassis_tunnel *
+chassis_tunnel_find(const struct hmap *chassis_tunnels, const char *chassis_id,
+ char *encap_ip)
+{
+ /*
+ * If the specific encap_ip is given, look for the chassisid_ip entry,
+ * else return the 1st found entry for the chassis.
+ */
+ struct chassis_tunnel *tun = NULL;
+ HMAP_FOR_EACH_WITH_HASH (tun, hmap_node, hash_string(chassis_id, 0),
+ chassis_tunnels) {
+ if (encaps_tunnel_id_match(tun->chassis_id, chassis_id, encap_ip)) {
+ return tun;
+ }
+ }
+ return NULL;
+}
+
/* static functions. */
static struct local_datapath *
local_datapath_add__(struct hmap *local_datapaths,
@@ -19,10 +19,14 @@
/* OVS includes. */
#include "include/openvswitch/shash.h"
#include "lib/smap.h"
+#include "lib/simap.h"
struct sbrec_datapath_binding;
struct sbrec_port_binding;
+struct sbrec_chassis;
struct ovsdb_idl_index;
+struct ovsrec_bridge;
+struct ovsrec_interface_table;
/* A logical datapath that has some relevance to this hypervisor. A logical
* datapath D is relevant to hypervisor H if:
@@ -108,4 +112,39 @@ void tracked_datapath_lport_add(const struct sbrec_port_binding *,
struct hmap *tracked_datapaths);
void tracked_datapaths_destroy(struct hmap *tracked_datapaths);
+/* Must be a bit-field ordered from most-preferred (higher number) to
+ * least-preferred (lower number). */
+enum chassis_tunnel_type {
+ GENEVE = 1 << 2,
+ STT = 1 << 1,
+ VXLAN = 1 << 0
+};
+
+/* Maps from a chassis to the OpenFlow port number of the tunnel that can be
+ * used to reach that chassis. */
+struct chassis_tunnel {
+ struct hmap_node hmap_node;
+ char *chassis_id;
+ ofp_port_t ofport;
+ enum chassis_tunnel_type type;
+};
+
+void local_nonvif_data_run(const struct ovsrec_bridge *br_int,
+ const struct sbrec_chassis *,
+ struct simap *patch_ofports,
+ struct hmap *chassis_tunnels);
+
+bool local_nonvif_data_handle_ovs_iface_changes(
+ const struct ovsrec_interface_table *);
+
+struct chassis_tunnel *chassis_tunnel_find(const struct hmap *chassis_tunnels,
+ const char *chassis_id,
+ char *encap_ip);
+
+bool get_chassis_tunnel_ofport(const struct hmap *chassis_tunnels,
+ const char *chassis_name, char *encap_ip,
+ ofp_port_t *ofport);
+
+void chassis_tunnels_destroy(struct hmap *chassis_tunnels);
+
#endif /* controller/local_data.h */
@@ -2038,6 +2038,78 @@ load_balancers_by_dp_cleanup(struct hmap *lbs)
free(lbs);
}
+/* Engine node which is used to handle the Non VIF data like
+ * - OVS patch ports
+ * - Tunnel ports and the related chassis information.
+ */
+struct ed_type_non_vif_data {
+ struct simap patch_ofports; /* simap of patch ovs ports. */
+ struct hmap chassis_tunnels; /* hmap of 'struct chassis_tunnel' from the
+ * tunnel OVS ports. */
+};
+
+static void *
+en_non_vif_data_init(struct engine_node *node OVS_UNUSED,
+ struct engine_arg *arg OVS_UNUSED)
+{
+ struct ed_type_non_vif_data *data = xzalloc(sizeof *data);
+ simap_init(&data->patch_ofports);
+ hmap_init(&data->chassis_tunnels);
+ return data;
+}
+
+static void
+en_non_vif_data_cleanup(void *data OVS_UNUSED)
+{
+ struct ed_type_non_vif_data *ed_non_vif_data = data;
+ simap_destroy(&ed_non_vif_data->patch_ofports);
+ chassis_tunnels_destroy(&ed_non_vif_data->chassis_tunnels);
+}
+
+static void
+en_non_vif_data_run(struct engine_node *node, void *data)
+{
+ struct ed_type_non_vif_data *ed_non_vif_data = data;
+ simap_destroy(&ed_non_vif_data->patch_ofports);
+ chassis_tunnels_destroy(&ed_non_vif_data->chassis_tunnels);
+ simap_init(&ed_non_vif_data->patch_ofports);
+ hmap_init(&ed_non_vif_data->chassis_tunnels);
+
+ struct ovsrec_open_vswitch_table *ovs_table =
+ (struct ovsrec_open_vswitch_table *)EN_OVSDB_GET(
+ engine_get_input("OVS_open_vswitch", node));
+ struct ovsrec_bridge_table *bridge_table =
+ (struct ovsrec_bridge_table *)EN_OVSDB_GET(
+ engine_get_input("OVS_bridge", node));
+
+ const struct ovsrec_bridge *br_int = get_br_int(bridge_table, ovs_table);
+ const char *chassis_id = get_ovs_chassis_id(ovs_table);
+ ovs_assert(br_int && chassis_id);
+
+ struct ovsdb_idl_index *sbrec_chassis_by_name =
+ engine_ovsdb_node_get_index(
+ engine_get_input("SB_chassis", node),
+ "name");
+
+ const struct sbrec_chassis *chassis
+ = chassis_lookup_by_name(sbrec_chassis_by_name, chassis_id);
+ ovs_assert(chassis);
+
+ local_nonvif_data_run(br_int, chassis, &ed_non_vif_data->patch_ofports,
+ &ed_non_vif_data->chassis_tunnels);
+ engine_set_node_state(node, EN_UPDATED);
+}
+
+static bool
+non_vif_data_ovs_iface_handler(struct engine_node *node, void *data OVS_UNUSED)
+{
+ struct ovsrec_interface_table *iface_table =
+ (struct ovsrec_interface_table *)EN_OVSDB_GET(
+ engine_get_input("OVS_interface", node));
+
+ return local_nonvif_data_handle_ovs_iface_changes(iface_table);
+}
+
struct lflow_output_persistent_data {
uint32_t conj_id_ofs;
struct lflow_cache *lflow_cache;
@@ -2061,6 +2133,7 @@ struct ed_type_lflow_output {
static void
init_lflow_ctx(struct engine_node *node,
struct ed_type_runtime_data *rt_data,
+ struct ed_type_non_vif_data *non_vif_data,
struct ed_type_lflow_output *fo,
struct lflow_ctx_in *l_ctx_in,
struct lflow_ctx_out *l_ctx_out)
@@ -2167,6 +2240,7 @@ init_lflow_ctx(struct engine_node *node,
l_ctx_in->port_groups = port_groups;
l_ctx_in->active_tunnels = &rt_data->active_tunnels;
l_ctx_in->related_lport_ids = &rt_data->related_lports.lport_ids;
+ l_ctx_in->chassis_tunnels = &non_vif_data->chassis_tunnels;
l_ctx_out->flow_table = &fo->flow_table;
l_ctx_out->group_table = &fo->group_table;
@@ -2206,6 +2280,8 @@ en_lflow_output_run(struct engine_node *node, void *data)
{
struct ed_type_runtime_data *rt_data =
engine_get_input_data("runtime_data", node);
+ struct ed_type_non_vif_data *non_vif_data =
+ engine_get_input_data("non_vif_data", node);
struct ovsrec_open_vswitch_table *ovs_table =
(struct ovsrec_open_vswitch_table *)EN_OVSDB_GET(
@@ -2254,7 +2330,7 @@ en_lflow_output_run(struct engine_node *node, void *data)
struct lflow_ctx_in l_ctx_in;
struct lflow_ctx_out l_ctx_out;
- init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
+ init_lflow_ctx(node, rt_data, non_vif_data, fo, &l_ctx_in, &l_ctx_out);
lflow_run(&l_ctx_in, &l_ctx_out);
if (l_ctx_out.conj_id_overflow) {
@@ -2281,6 +2357,8 @@ lflow_output_sb_logical_flow_handler(struct engine_node *node, void *data)
{
struct ed_type_runtime_data *rt_data =
engine_get_input_data("runtime_data", node);
+ struct ed_type_non_vif_data *non_vif_data =
+ engine_get_input_data("non_vif_data", node);
struct ovsrec_open_vswitch_table *ovs_table =
(struct ovsrec_open_vswitch_table *)EN_OVSDB_GET(
engine_get_input("OVS_open_vswitch", node));
@@ -2293,7 +2371,7 @@ lflow_output_sb_logical_flow_handler(struct engine_node *node, void *data)
struct ed_type_lflow_output *fo = data;
struct lflow_ctx_in l_ctx_in;
struct lflow_ctx_out l_ctx_out;
- init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
+ init_lflow_ctx(node, rt_data, non_vif_data, fo, &l_ctx_in, &l_ctx_out);
bool handled = lflow_handle_changed_flows(&l_ctx_in, &l_ctx_out);
@@ -2331,12 +2409,14 @@ lflow_output_sb_multicast_group_handler(struct engine_node *node, void *data)
{
struct ed_type_runtime_data *rt_data =
engine_get_input_data("runtime_data", node);
+ struct ed_type_non_vif_data *non_vif_data =
+ engine_get_input_data("non_vif_data", node);
struct ed_type_lflow_output *lfo = data;
struct lflow_ctx_in l_ctx_in;
struct lflow_ctx_out l_ctx_out;
- init_lflow_ctx(node, rt_data, lfo, &l_ctx_in, &l_ctx_out);
+ init_lflow_ctx(node, rt_data, non_vif_data, lfo, &l_ctx_in, &l_ctx_out);
if (!lflow_handle_changed_mc_groups(&l_ctx_in, &l_ctx_out)) {
return false;
}
@@ -2350,12 +2430,14 @@ lflow_output_sb_port_binding_handler(struct engine_node *node, void *data)
{
struct ed_type_runtime_data *rt_data =
engine_get_input_data("runtime_data", node);
+ struct ed_type_non_vif_data *non_vif_data =
+ engine_get_input_data("non_vif_data", node);
struct ed_type_lflow_output *lfo = data;
struct lflow_ctx_in l_ctx_in;
struct lflow_ctx_out l_ctx_out;
- init_lflow_ctx(node, rt_data, lfo, &l_ctx_in, &l_ctx_out);
+ init_lflow_ctx(node, rt_data, non_vif_data, lfo, &l_ctx_in, &l_ctx_out);
if (!lflow_handle_changed_port_bindings(&l_ctx_in, &l_ctx_out)) {
return false;
}
@@ -2370,6 +2452,8 @@ _lflow_output_resource_ref_handler(struct engine_node *node, void *data,
{
struct ed_type_runtime_data *rt_data =
engine_get_input_data("runtime_data", node);
+ struct ed_type_non_vif_data *non_vif_data =
+ engine_get_input_data("non_vif_data", node);
struct ed_type_addr_sets *as_data =
engine_get_input_data("addr_sets", node);
@@ -2401,7 +2485,7 @@ _lflow_output_resource_ref_handler(struct engine_node *node, void *data,
struct lflow_ctx_in l_ctx_in;
struct lflow_ctx_out l_ctx_out;
- init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
+ init_lflow_ctx(node, rt_data, non_vif_data, fo, &l_ctx_in, &l_ctx_out);
bool changed;
const char *ref_name;
@@ -2488,6 +2572,8 @@ lflow_output_runtime_data_handler(struct engine_node *node,
{
struct ed_type_runtime_data *rt_data =
engine_get_input_data("runtime_data", node);
+ struct ed_type_non_vif_data *non_vif_data =
+ engine_get_input_data("non_vif_data", node);
/* There is no tracked data. Fall back to full recompute of
* flow_output. */
@@ -2507,7 +2593,7 @@ lflow_output_runtime_data_handler(struct engine_node *node,
struct lflow_ctx_out l_ctx_out;
struct ed_type_lflow_output *fo = data;
struct hmap *lbs = NULL;
- init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
+ init_lflow_ctx(node, rt_data, non_vif_data, fo, &l_ctx_in, &l_ctx_out);
struct tracked_datapath *tdp;
HMAP_FOR_EACH (tdp, node, tracked_dp_bindings) {
@@ -2547,11 +2633,13 @@ lflow_output_sb_load_balancer_handler(struct engine_node *node, void *data)
{
struct ed_type_runtime_data *rt_data =
engine_get_input_data("runtime_data", node);
+ struct ed_type_non_vif_data *non_vif_data =
+ engine_get_input_data("non_vif_data", node);
struct ed_type_lflow_output *fo = data;
struct lflow_ctx_in l_ctx_in;
struct lflow_ctx_out l_ctx_out;
- init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
+ init_lflow_ctx(node, rt_data, non_vif_data, fo, &l_ctx_in, &l_ctx_out);
bool handled = lflow_handle_changed_lbs(&l_ctx_in, &l_ctx_out);
@@ -2564,11 +2652,13 @@ lflow_output_sb_fdb_handler(struct engine_node *node, void *data)
{
struct ed_type_runtime_data *rt_data =
engine_get_input_data("runtime_data", node);
+ struct ed_type_non_vif_data *non_vif_data =
+ engine_get_input_data("non_vif_data", node);
struct ed_type_lflow_output *fo = data;
struct lflow_ctx_in l_ctx_in;
struct lflow_ctx_out l_ctx_out;
- init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
+ init_lflow_ctx(node, rt_data, non_vif_data, fo, &l_ctx_in, &l_ctx_out);
bool handled = lflow_handle_changed_fdbs(&l_ctx_in, &l_ctx_out);
@@ -2583,6 +2673,7 @@ struct ed_type_pflow_output {
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,
struct physical_ctx *p_ctx)
{
struct ovsdb_idl_index *sbrec_port_binding_by_name =
@@ -2624,10 +2715,6 @@ static void init_physical_ctx(struct engine_node *node,
ovs_assert(br_int && chassis);
- struct ovsrec_interface_table *iface_table =
- (struct ovsrec_interface_table *)EN_OVSDB_GET(
- engine_get_input("OVS_interface", node));
-
struct ed_type_ct_zones *ct_zones_data =
engine_get_input_data("ct_zones", node);
struct simap *ct_zones = &ct_zones_data->current;
@@ -2637,7 +2724,6 @@ static void init_physical_ctx(struct engine_node *node,
p_ctx->mc_group_table = multicast_group_table;
p_ctx->br_int = br_int;
p_ctx->chassis_table = chassis_table;
- p_ctx->iface_table = iface_table;
p_ctx->chassis = chassis;
p_ctx->active_tunnels = &rt_data->active_tunnels;
p_ctx->local_datapaths = &rt_data->local_datapaths;
@@ -2645,6 +2731,8 @@ static void init_physical_ctx(struct engine_node *node,
p_ctx->ct_zones = ct_zones;
p_ctx->mff_ovn_geneve = ed_mff_ovn_geneve->mff_ovn_geneve;
p_ctx->local_bindings = &rt_data->lbinding_data.bindings;
+ p_ctx->patch_ofports = &non_vif_data->patch_ofports;
+ p_ctx->chassis_tunnels = &non_vif_data->chassis_tunnels;
}
static void *
@@ -2677,9 +2765,11 @@ en_pflow_output_run(struct engine_node *node, void *data)
struct ed_type_runtime_data *rt_data =
engine_get_input_data("runtime_data", node);
+ struct ed_type_non_vif_data *non_vif_data =
+ engine_get_input_data("non_vif_data", node);
struct physical_ctx p_ctx;
- init_physical_ctx(node, rt_data, &p_ctx);
+ init_physical_ctx(node, rt_data, non_vif_data, &p_ctx);
physical_run(&p_ctx, pflow_table);
engine_set_node_state(node, EN_UPDATED);
@@ -2691,17 +2781,23 @@ pflow_output_sb_port_binding_handler(struct engine_node *node,
{
struct ed_type_runtime_data *rt_data =
engine_get_input_data("runtime_data", node);
+ struct ed_type_non_vif_data *non_vif_data =
+ engine_get_input_data("non_vif_data", node);
struct ed_type_pflow_output *pfo = data;
struct physical_ctx p_ctx;
- init_physical_ctx(node, rt_data, &p_ctx);
+ init_physical_ctx(node, rt_data, non_vif_data, &p_ctx);
/* We handle port-binding changes for physical flow processing
* only. flow_output runtime data handler takes care of processing
* logical flows for any port binding changes.
*/
- physical_handle_port_binding_changes(&p_ctx, &pfo->flow_table);
+ const struct sbrec_port_binding *pb;
+ SBREC_PORT_BINDING_TABLE_FOR_EACH_TRACKED (pb, p_ctx.port_binding_table) {
+ bool removed = sbrec_port_binding_is_deleted(pb);
+ physical_handle_flows_for_lport(pb, removed, &p_ctx, &pfo->flow_table);
+ }
engine_set_node_state(node, EN_UPDATED);
return true;
@@ -2712,11 +2808,13 @@ pflow_output_sb_multicast_group_handler(struct engine_node *node, void *data)
{
struct ed_type_runtime_data *rt_data =
engine_get_input_data("runtime_data", node);
+ struct ed_type_non_vif_data *non_vif_data =
+ engine_get_input_data("non_vif_data", node);
struct ed_type_pflow_output *pfo = data;
struct physical_ctx p_ctx;
- init_physical_ctx(node, rt_data, &p_ctx);
+ init_physical_ctx(node, rt_data, non_vif_data, &p_ctx);
physical_handle_mc_group_changes(&p_ctx, &pfo->flow_table);
@@ -2725,19 +2823,49 @@ pflow_output_sb_multicast_group_handler(struct engine_node *node, void *data)
}
static bool
-pflow_output_ovs_iface_handler(struct engine_node *node OVS_UNUSED,
- void *data OVS_UNUSED)
+pflow_output_runtime_data_handler(struct engine_node *node, void *data)
{
struct ed_type_runtime_data *rt_data =
engine_get_input_data("runtime_data", node);
+ struct ed_type_non_vif_data *non_vif_data =
+ engine_get_input_data("non_vif_data", node);
+
+ /* There is no tracked data. Fall back to full recompute of
+ * pflow_output. */
+ if (!rt_data->tracked) {
+ return false;
+ }
+
+ struct hmap *tracked_dp_bindings = &rt_data->tracked_dp_bindings;
+ if (hmap_is_empty(tracked_dp_bindings)) {
+ return true;
+ }
struct ed_type_pflow_output *pfo = data;
struct physical_ctx p_ctx;
- init_physical_ctx(node, rt_data, &p_ctx);
+ init_physical_ctx(node, rt_data, non_vif_data, &p_ctx);
+
+ struct tracked_datapath *tdp;
+ HMAP_FOR_EACH (tdp, node, tracked_dp_bindings) {
+ if (tdp->tracked_type != TRACKED_RESOURCE_UPDATED) {
+ /* Fall back to full recompute when a local datapath
+ * is added or deleted. */
+ return false;
+ }
+
+ struct shash_node *shash_node;
+ SHASH_FOR_EACH (shash_node, &tdp->lports) {
+ struct tracked_lport *lport = shash_node->data;
+ bool removed =
+ lport->tracked_type == TRACKED_RESOURCE_REMOVED ? true: false;
+ physical_handle_flows_for_lport(lport->pb, removed, &p_ctx,
+ &pfo->flow_table);
+ }
+ }
engine_set_node_state(node, EN_UPDATED);
- return physical_handle_ovs_iface_changes(&p_ctx, &pfo->flow_table);
+ return true;
}
static void *
@@ -2997,6 +3125,7 @@ main(int argc, char *argv[])
/* Define inc-proc-engine nodes. */
ENGINE_NODE_CUSTOM_DATA(ct_zones, "ct_zones");
ENGINE_NODE_WITH_CLEAR_TRACK_DATA(runtime_data, "runtime_data");
+ ENGINE_NODE(non_vif_data, "non_vif_data");
ENGINE_NODE(mff_ovn_geneve, "mff_ovn_geneve");
ENGINE_NODE(ofctrl_is_connected, "ofctrl_is_connected");
ENGINE_NODE(pflow_output, "physical_flow_output");
@@ -3024,11 +3153,17 @@ main(int argc, char *argv[])
engine_add_input(&en_port_groups, &en_runtime_data,
port_groups_runtime_data_handler);
+ engine_add_input(&en_non_vif_data, &en_ovs_open_vswitch, NULL);
+ engine_add_input(&en_non_vif_data, &en_ovs_bridge, NULL);
+ engine_add_input(&en_non_vif_data, &en_sb_chassis, NULL);
+ engine_add_input(&en_non_vif_data, &en_ovs_interface,
+ non_vif_data_ovs_iface_handler);
+
/* Note: The order of inputs is important, all OVS interface changes must
* be handled before any ct_zone changes.
*/
- engine_add_input(&en_pflow_output, &en_ovs_interface,
- pflow_output_ovs_iface_handler);
+ engine_add_input(&en_pflow_output, &en_non_vif_data,
+ NULL);
engine_add_input(&en_pflow_output, &en_ct_zones, NULL);
engine_add_input(&en_pflow_output, &en_sb_chassis,
pflow_lflow_output_sb_chassis_handler);
@@ -3039,7 +3174,7 @@ main(int argc, char *argv[])
pflow_output_sb_multicast_group_handler);
engine_add_input(&en_pflow_output, &en_runtime_data,
- NULL);
+ pflow_output_runtime_data_handler);
engine_add_input(&en_pflow_output, &en_sb_encap, NULL);
engine_add_input(&en_pflow_output, &en_mff_ovn_geneve, NULL);
engine_add_input(&en_pflow_output, &en_ovs_open_vswitch, NULL);
@@ -3051,6 +3186,8 @@ main(int argc, char *argv[])
lflow_output_port_groups_handler);
engine_add_input(&en_lflow_output, &en_runtime_data,
lflow_output_runtime_data_handler);
+ engine_add_input(&en_lflow_output, &en_non_vif_data,
+ NULL);
engine_add_input(&en_lflow_output, &en_sb_multicast_group,
lflow_output_sb_multicast_group_handler);
@@ -45,14 +45,6 @@ const struct ovsrec_bridge *get_bridge(const struct ovsrec_bridge_table *,
struct sbrec_encap *preferred_encap(const struct sbrec_chassis *);
-/* Must be a bit-field ordered from most-preferred (higher number) to
- * least-preferred (lower number). */
-enum chassis_tunnel_type {
- GENEVE = 1 << 2,
- STT = 1 << 1,
- VXLAN = 1 << 0
-};
-
uint32_t get_tunnel_type(const char *name);
struct pb_ld_binding {
@@ -86,46 +86,6 @@ physical_register_ovs_idl(struct ovsdb_idl *ovs_idl)
ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_external_ids);
}
-static struct simap localvif_to_ofport =
- SIMAP_INITIALIZER(&localvif_to_ofport);
-static struct hmap tunnels = HMAP_INITIALIZER(&tunnels);
-
-/* Maps from a chassis to the OpenFlow port number of the tunnel that can be
- * used to reach that chassis. */
-struct chassis_tunnel {
- struct hmap_node hmap_node;
- char *chassis_id;
- ofp_port_t ofport;
- enum chassis_tunnel_type type;
-};
-
-/*
- * This function looks up the list of tunnel ports (provided by
- * ovn-chassis-id ports) and returns the tunnel for the given chassid-id and
- * encap-ip. The ovn-chassis-id is formed using the chassis-id and encap-ip.
- * The list is hashed using the chassis-id. If the encap-ip is not specified,
- * it means we'll just return a tunnel for that chassis-id, i.e. we just check
- * for chassis-id and if there is a match, we'll return the tunnel.
- * If encap-ip is also provided we use both chassis-id and encap-ip to do
- * a more specific lookup.
- */
-static struct chassis_tunnel *
-chassis_tunnel_find(const char *chassis_id, char *encap_ip)
-{
- /*
- * If the specific encap_ip is given, look for the chassisid_ip entry,
- * else return the 1st found entry for the chassis.
- */
- struct chassis_tunnel *tun = NULL;
- HMAP_FOR_EACH_WITH_HASH (tun, hmap_node, hash_string(chassis_id, 0),
- &tunnels) {
- if (encaps_tunnel_id_match(tun->chassis_id, chassis_id, encap_ip)) {
- return tun;
- }
- }
- return NULL;
-}
-
static void
put_load(uint64_t value, enum mf_field_id dst, int ofs, int n_bits,
struct ofpbuf *ofpacts)
@@ -166,17 +126,18 @@ put_resubmit(uint8_t table_id, struct ofpbuf *ofpacts)
* from the associated encap.
*/
static struct chassis_tunnel *
-get_port_binding_tun(const struct sbrec_port_binding *binding)
+get_port_binding_tun(const struct sbrec_port_binding *binding,
+ const struct hmap *chassis_tunnels)
{
struct sbrec_encap *encap = binding->encap;
struct sbrec_chassis *chassis = binding->chassis;
struct chassis_tunnel *tun = NULL;
if (encap) {
- tun = chassis_tunnel_find(chassis->name, encap->ip);
+ tun = chassis_tunnel_find(chassis_tunnels, chassis->name, encap->ip);
}
if (!tun) {
- tun = chassis_tunnel_find(chassis->name, NULL);
+ tun = chassis_tunnel_find(chassis_tunnels, chassis->name, NULL);
}
return tun;
}
@@ -325,12 +286,13 @@ put_remote_port_redirect_overlay(const struct
uint32_t port_key,
struct match *match,
struct ofpbuf *ofpacts_p,
+ const struct hmap *chassis_tunnels,
struct ovn_desired_flow_table *flow_table)
{
if (!is_ha_remote) {
/* Setup encapsulation */
const struct chassis_tunnel *rem_tun =
- get_port_binding_tun(binding);
+ get_port_binding_tun(binding, chassis_tunnels);
if (!rem_tun) {
return;
}
@@ -348,10 +310,10 @@ put_remote_port_redirect_overlay(const struct
continue;
}
if (!tun) {
- tun = chassis_tunnel_find(ch->name, NULL);
+ tun = chassis_tunnel_find(chassis_tunnels, ch->name, NULL);
} else {
struct chassis_tunnel *chassis_tunnel =
- chassis_tunnel_find(ch->name, NULL);
+ chassis_tunnel_find(chassis_tunnels, ch->name, NULL);
if (chassis_tunnel &&
tun->type != chassis_tunnel->type) {
static struct vlog_rate_limit rl =
@@ -385,7 +347,7 @@ put_remote_port_redirect_overlay(const struct
if (!ch) {
continue;
}
- tun = chassis_tunnel_find(ch->name, NULL);
+ tun = chassis_tunnel_find(chassis_tunnels, ch->name, NULL);
if (!tun) {
continue;
}
@@ -926,6 +888,9 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
const struct simap *ct_zones,
const struct sset *active_tunnels,
const struct hmap *local_datapaths,
+ const struct shash *local_bindings,
+ const struct simap *patch_ofports,
+ const struct hmap *chassis_tunnels,
const struct sbrec_port_binding *binding,
const struct sbrec_chassis *chassis,
struct ovn_desired_flow_table *flow_table,
@@ -1082,17 +1047,25 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
if (!binding->tag) {
goto out;
}
- ofport = u16_to_ofp(simap_get(&localvif_to_ofport,
- binding->parent_port));
+ ofport = local_binding_get_lport_ofport(local_bindings,
+ binding->parent_port);
if (ofport) {
tag = *binding->tag;
nested_container = true;
parent_port = lport_lookup_by_name(
sbrec_port_binding_by_name, binding->parent_port);
}
- } else {
- ofport = u16_to_ofp(simap_get(&localvif_to_ofport,
+ } else if (!strcmp(binding->type, "localnet")
+ || !strcmp(binding->type, "l2gateway")) {
+
+ ofport = u16_to_ofp(simap_get(patch_ofports,
binding->logical_port));
+ if (ofport && binding->tag) {
+ tag = *binding->tag;
+ }
+ } else {
+ ofport = local_binding_get_lport_ofport(local_bindings,
+ binding->logical_port);
const char *requested_chassis = smap_get(&binding->options,
"requested-chassis");
if (ofport && requested_chassis && requested_chassis[0] &&
@@ -1103,12 +1076,6 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
*/
ofport = 0;
}
-
- if ((!strcmp(binding->type, "localnet")
- || !strcmp(binding->type, "l2gateway"))
- && ofport && binding->tag) {
- tag = *binding->tag;
- }
}
bool is_ha_remote = false;
@@ -1119,7 +1086,7 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
/* It is remote port, may be reached by tunnel or localnet port */
is_remote = true;
if (localnet_port) {
- ofport = u16_to_ofp(simap_get(&localvif_to_ofport,
+ ofport = u16_to_ofp(simap_get(patch_ofports,
localnet_port->logical_port));
if (!ofport) {
goto out;
@@ -1130,7 +1097,8 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
if (!binding->chassis) {
goto out;
}
- tun = chassis_tunnel_find(binding->chassis->name, NULL);
+ tun = chassis_tunnel_find(chassis_tunnels,
+ binding->chassis->name, NULL);
if (!tun) {
goto out;
}
@@ -1384,7 +1352,7 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
put_remote_port_redirect_overlay(binding, is_ha_remote,
ha_ch_ordered, mff_ovn_geneve,
tun, port_key, &match, ofpacts_p,
- flow_table);
+ chassis_tunnels, flow_table);
}
}
out:
@@ -1397,8 +1365,11 @@ static void
consider_mc_group(enum mf_field_id mff_ovn_geneve,
const struct simap *ct_zones,
const struct hmap *local_datapaths,
+ struct shash *local_bindings,
+ struct simap *patch_ofports,
const struct sbrec_chassis *chassis,
const struct sbrec_multicast_group *mc,
+ const struct hmap *chassis_tunnels,
struct ovn_desired_flow_table *flow_table)
{
uint32_t dp_key = mc->datapath->tunnel_key;
@@ -1445,19 +1416,21 @@ consider_mc_group(enum mf_field_id mff_ovn_geneve,
put_load(zone_id, MFF_LOG_CT_ZONE, 0, 32, &ofpacts);
}
+ const char *lport_name = (port->parent_port && *port->parent_port) ?
+ port->parent_port : port->logical_port;
+
if (!strcmp(port->type, "patch")) {
put_load(port->tunnel_key, MFF_LOG_OUTPORT, 0, 32,
&remote_ofpacts);
put_resubmit(OFTABLE_CHECK_LOOPBACK, &remote_ofpacts);
- } else if (simap_contains(&localvif_to_ofport,
- (port->parent_port && *port->parent_port)
- ? port->parent_port : port->logical_port)
+ } else if (local_binding_get_primary_pb(local_bindings, lport_name)
+ || simap_contains(patch_ofports, port->logical_port)
|| (!strcmp(port->type, "l3gateway")
&& port->chassis == chassis)) {
put_load(port->tunnel_key, MFF_LOG_OUTPORT, 0, 32, &ofpacts);
put_resubmit(OFTABLE_CHECK_LOOPBACK, &ofpacts);
- } else if (port->chassis && !get_localnet_port(local_datapaths,
- mc->datapath->tunnel_key)) {
+ } else if (port->chassis && !get_localnet_port(
+ local_datapaths, mc->datapath->tunnel_key)) {
/* Add remote chassis only when localnet port not exist,
* otherwise multicast will reach remote ports through localnet
* port. */
@@ -1498,7 +1471,7 @@ consider_mc_group(enum mf_field_id mff_ovn_geneve,
const struct chassis_tunnel *prev = NULL;
SSET_FOR_EACH (chassis_name, &remote_chassis) {
const struct chassis_tunnel *tun
- = chassis_tunnel_find(chassis_name, NULL);
+ = chassis_tunnel_find(chassis_tunnels, chassis_name, NULL);
if (!tun) {
continue;
}
@@ -1525,41 +1498,50 @@ consider_mc_group(enum mf_field_id mff_ovn_geneve,
sset_destroy(&remote_chassis);
}
-/* Replaces 'old' by 'new' (destroying 'new'). Returns true if 'old' and 'new'
- * contained different data, false if they were the same. */
-static bool
-update_ofports(struct simap *old, struct simap *new)
-{
- bool changed = !simap_equal(old, new);
- simap_swap(old, new);
- simap_destroy(new);
- return changed;
-}
-
void
-physical_handle_port_binding_changes(struct physical_ctx *p_ctx,
- struct ovn_desired_flow_table *flow_table)
+physical_handle_flows_for_lport(const struct sbrec_port_binding *pb,
+ bool removed, struct physical_ctx *p_ctx,
+ struct ovn_desired_flow_table *flow_table)
{
- const struct sbrec_port_binding *binding;
- struct ofpbuf ofpacts;
- ofpbuf_init(&ofpacts, 0);
- SBREC_PORT_BINDING_TABLE_FOR_EACH_TRACKED (binding,
- p_ctx->port_binding_table) {
- if (sbrec_port_binding_is_deleted(binding)) {
- ofctrl_remove_flows(flow_table, &binding->header_.uuid);
- } else {
- if (!sbrec_port_binding_is_new(binding)) {
- ofctrl_remove_flows(flow_table, &binding->header_.uuid);
- }
+ ofctrl_remove_flows(flow_table, &pb->header_.uuid);
+
+ if (!strcmp(pb->type, "external")) {
+ /* External lports have a dependency on the localnet port.
+ * We need to remove the flows of the localnet port as well
+ * and re-consider adding the flows for it.
+ */
+ struct local_datapath *ldp =
+ get_local_datapath(p_ctx->local_datapaths,
+ pb->datapath->tunnel_key);
+ if (ldp && ldp->localnet_port) {
+ struct ofpbuf ofpacts;
+ ofctrl_remove_flows(flow_table, &ldp->localnet_port->header_.uuid);
+ ofpbuf_init(&ofpacts, 0);
consider_port_binding(p_ctx->sbrec_port_binding_by_name,
p_ctx->mff_ovn_geneve, p_ctx->ct_zones,
p_ctx->active_tunnels,
p_ctx->local_datapaths,
- binding, p_ctx->chassis,
+ p_ctx->local_bindings,
+ p_ctx->patch_ofports,
+ p_ctx->chassis_tunnels,
+ ldp->localnet_port, p_ctx->chassis,
flow_table, &ofpacts);
+ ofpbuf_uninit(&ofpacts);
}
}
- ofpbuf_uninit(&ofpacts);
+
+ if (!removed) {
+ struct ofpbuf ofpacts;
+ ofpbuf_init(&ofpacts, 0);
+ consider_port_binding(p_ctx->sbrec_port_binding_by_name,
+ p_ctx->mff_ovn_geneve, p_ctx->ct_zones,
+ p_ctx->active_tunnels, p_ctx->local_datapaths,
+ p_ctx->local_bindings,
+ p_ctx->patch_ofports,
+ p_ctx->chassis_tunnels, pb,
+ p_ctx->chassis, flow_table, &ofpacts);
+ ofpbuf_uninit(&ofpacts);
+ }
}
void
@@ -1575,8 +1557,11 @@ physical_handle_mc_group_changes(struct physical_ctx *p_ctx,
ofctrl_remove_flows(flow_table, &mc->header_.uuid);
}
consider_mc_group(p_ctx->mff_ovn_geneve, p_ctx->ct_zones,
- p_ctx->local_datapaths,
- p_ctx->chassis, mc, flow_table);
+ p_ctx->local_datapaths, p_ctx->local_bindings,
+ p_ctx->patch_ofports,
+ p_ctx->chassis, mc,
+ p_ctx->chassis_tunnels,
+ flow_table);
}
}
}
@@ -1592,135 +1577,6 @@ physical_run(struct physical_ctx *p_ctx,
uuid_generate(hc_uuid);
}
- /* This bool tracks physical mapping changes. */
- bool physical_map_changed = false;
-
- struct simap new_localvif_to_ofport =
- SIMAP_INITIALIZER(&new_localvif_to_ofport);
- struct simap new_tunnel_to_ofport =
- SIMAP_INITIALIZER(&new_tunnel_to_ofport);
- for (int i = 0; i < p_ctx->br_int->n_ports; i++) {
- const struct ovsrec_port *port_rec = p_ctx->br_int->ports[i];
- if (!strcmp(port_rec->name, p_ctx->br_int->name)) {
- continue;
- }
-
- const char *tunnel_id = smap_get(&port_rec->external_ids,
- "ovn-chassis-id");
- if (tunnel_id && encaps_tunnel_id_match(tunnel_id,
- p_ctx->chassis->name,
- NULL)) {
- continue;
- }
-
- const char *localnet = smap_get(&port_rec->external_ids,
- "ovn-localnet-port");
- const char *l2gateway = smap_get(&port_rec->external_ids,
- "ovn-l2gateway-port");
-
- for (int j = 0; j < port_rec->n_interfaces; j++) {
- const struct ovsrec_interface *iface_rec = port_rec->interfaces[j];
-
- /* Get OpenFlow port number. */
- if (!iface_rec->n_ofport) {
- continue;
- }
- int64_t ofport = iface_rec->ofport[0];
- if (ofport < 1 || ofport > ofp_to_u16(OFPP_MAX)) {
- continue;
- }
-
- /* Record as patch to local net, logical patch port, chassis, or
- * local logical port. */
- bool is_patch = !strcmp(iface_rec->type, "patch");
- if (is_patch && localnet) {
- /* localnet patch ports can be handled just like VIFs. */
- simap_put(&new_localvif_to_ofport, localnet, ofport);
- break;
- } else if (is_patch && l2gateway) {
- /* L2 gateway patch ports can be handled just like VIFs. */
- simap_put(&new_localvif_to_ofport, l2gateway, ofport);
- break;
- } else if (tunnel_id) {
- enum chassis_tunnel_type tunnel_type;
- if (!strcmp(iface_rec->type, "geneve")) {
- tunnel_type = GENEVE;
- if (!p_ctx->mff_ovn_geneve) {
- continue;
- }
- } else if (!strcmp(iface_rec->type, "stt")) {
- tunnel_type = STT;
- } else if (!strcmp(iface_rec->type, "vxlan")) {
- tunnel_type = VXLAN;
- } else {
- continue;
- }
-
- simap_put(&new_tunnel_to_ofport, tunnel_id, ofport);
- /*
- * We split the tunnel_id to get the chassis-id
- * and hash the tunnel list on the chassis-id. The
- * reason to use the chassis-id alone is because
- * there might be cases (multicast, gateway chassis)
- * where we need to tunnel to the chassis, but won't
- * have the encap-ip specifically.
- */
- char *hash_id = NULL;
- char *ip = NULL;
-
- if (!encaps_tunnel_id_parse(tunnel_id, &hash_id, &ip)) {
- continue;
- }
- struct chassis_tunnel *tun = chassis_tunnel_find(hash_id, ip);
- if (tun) {
- /* If the tunnel's ofport has changed, update. */
- if (tun->ofport != u16_to_ofp(ofport) ||
- tun->type != tunnel_type) {
- tun->ofport = u16_to_ofp(ofport);
- tun->type = tunnel_type;
- physical_map_changed = true;
- }
- } else {
- tun = xmalloc(sizeof *tun);
- hmap_insert(&tunnels, &tun->hmap_node,
- hash_string(hash_id, 0));
- tun->chassis_id = xstrdup(tunnel_id);
- tun->ofport = u16_to_ofp(ofport);
- tun->type = tunnel_type;
- physical_map_changed = true;
- }
- free(hash_id);
- free(ip);
- break;
- } else {
- const char *iface_id = smap_get(&iface_rec->external_ids,
- "iface-id");
- if (iface_id) {
- simap_put(&new_localvif_to_ofport, iface_id, ofport);
- }
- }
- }
- }
-
- /* Remove tunnels that are no longer here. */
- struct chassis_tunnel *tun, *tun_next;
- HMAP_FOR_EACH_SAFE (tun, tun_next, hmap_node, &tunnels) {
- if (!simap_find(&new_tunnel_to_ofport, tun->chassis_id)) {
- hmap_remove(&tunnels, &tun->hmap_node);
- physical_map_changed = true;
- free(tun->chassis_id);
- free(tun);
- }
- }
-
- /* Capture changed or removed openflow ports. */
- physical_map_changed |= update_ofports(&localvif_to_ofport,
- &new_localvif_to_ofport);
- if (physical_map_changed) {
- /* Reprocess logical flow table immediately. */
- poll_immediate_wake();
- }
-
struct ofpbuf ofpacts;
ofpbuf_init(&ofpacts, 0);
@@ -1734,16 +1590,20 @@ physical_run(struct physical_ctx *p_ctx,
consider_port_binding(p_ctx->sbrec_port_binding_by_name,
p_ctx->mff_ovn_geneve, p_ctx->ct_zones,
p_ctx->active_tunnels, p_ctx->local_datapaths,
- binding, p_ctx->chassis,
- flow_table, &ofpacts);
+ p_ctx->local_bindings,
+ p_ctx->patch_ofports,
+ p_ctx->chassis_tunnels, binding,
+ p_ctx->chassis, flow_table, &ofpacts);
}
/* Handle output to multicast groups, in tables 32 and 33. */
const struct sbrec_multicast_group *mc;
SBREC_MULTICAST_GROUP_TABLE_FOR_EACH (mc, p_ctx->mc_group_table) {
consider_mc_group(p_ctx->mff_ovn_geneve, p_ctx->ct_zones,
- p_ctx->local_datapaths, p_ctx->chassis,
- mc, flow_table);
+ p_ctx->local_datapaths, p_ctx->local_bindings,
+ p_ctx->patch_ofports, p_ctx->chassis,
+ mc, p_ctx->chassis_tunnels,
+ flow_table);
}
/* Table 0, priority 100.
@@ -1758,7 +1618,8 @@ physical_run(struct physical_ctx *p_ctx,
* We set MFF_LOG_DATAPATH, MFF_LOG_INPORT, and MFF_LOG_OUTPORT from the
* tunnel key data where possible, then resubmit to table 33 to handle
* packets to the local hypervisor. */
- HMAP_FOR_EACH (tun, hmap_node, &tunnels) {
+ struct chassis_tunnel *tun;
+ HMAP_FOR_EACH (tun, hmap_node, p_ctx->chassis_tunnels) {
struct match match = MATCH_CATCHALL_INITIALIZER;
match_set_in_port(&match, tun->ofport);
@@ -1789,7 +1650,7 @@ physical_run(struct physical_ctx *p_ctx,
}
/* Handle ramp switch encapsulations. */
- HMAP_FOR_EACH (tun, hmap_node, &tunnels) {
+ HMAP_FOR_EACH (tun, hmap_node, p_ctx->chassis_tunnels) {
if (tun->type != VXLAN) {
continue;
}
@@ -1926,89 +1787,4 @@ physical_run(struct physical_ctx *p_ctx,
&ofpacts, hc_uuid);
ofpbuf_uninit(&ofpacts);
-
- simap_destroy(&new_tunnel_to_ofport);
-}
-
-bool
-physical_handle_ovs_iface_changes(struct physical_ctx *p_ctx,
- struct ovn_desired_flow_table *flow_table)
-{
- const struct ovsrec_interface *iface_rec;
- OVSREC_INTERFACE_TABLE_FOR_EACH_TRACKED (iface_rec, p_ctx->iface_table) {
- if (!strcmp(iface_rec->type, "geneve") ||
- !strcmp(iface_rec->type, "patch") ||
- !strcmp(iface_rec->type, "vxlan") ||
- !strcmp(iface_rec->type, "stt")) {
- return false;
- }
- }
-
- struct ofpbuf ofpacts;
- ofpbuf_init(&ofpacts, 0);
-
- OVSREC_INTERFACE_TABLE_FOR_EACH_TRACKED (iface_rec, p_ctx->iface_table) {
- const char *iface_id = smap_get(&iface_rec->external_ids, "iface-id");
- if (!iface_id) {
- continue;
- }
-
- const struct sbrec_port_binding *lb_pb =
- local_binding_get_primary_pb(p_ctx->local_bindings, iface_id);
- if (!lb_pb) {
- /* For regular VIFs (e.g. lsp) the upcoming port-binding update
- * will remove lfows related to the unclaimed ovs port.
- * Localport is a special case and it needs to be managed here
- * since the port is not binded and otherwise the related lfows
- * will not be cleared removing the ovs port.
- */
- lb_pb = lport_lookup_by_name(p_ctx->sbrec_port_binding_by_name,
- iface_id);
- if (!lb_pb || strcmp(lb_pb->type, "localport")) {
- continue;
- }
- }
-
- int64_t ofport = iface_rec->n_ofport ? *iface_rec->ofport : 0;
- if (ovsrec_interface_is_deleted(iface_rec)) {
- ofctrl_remove_flows(flow_table, &lb_pb->header_.uuid);
- simap_find_and_delete(&localvif_to_ofport, iface_id);
- } else {
- if (!ovsrec_interface_is_new(iface_rec)) {
- ofctrl_remove_flows(flow_table, &lb_pb->header_.uuid);
- }
-
- simap_put(&localvif_to_ofport, iface_id, ofport);
- consider_port_binding(p_ctx->sbrec_port_binding_by_name,
- p_ctx->mff_ovn_geneve, p_ctx->ct_zones,
- p_ctx->active_tunnels,
- p_ctx->local_datapaths,
- lb_pb, p_ctx->chassis,
- flow_table, &ofpacts);
- }
- }
-
- ofpbuf_uninit(&ofpacts);
- return true;
-}
-
-bool
-get_tunnel_ofport(const char *chassis_name, char *encap_ip, ofp_port_t *ofport)
-{
- struct chassis_tunnel *tun = NULL;
- tun = chassis_tunnel_find(chassis_name, encap_ip);
- if (!tun) {
- return false;
- }
-
- *ofport = tun->ofport;
- return true;
-}
-
-void
-physical_clear_unassoc_flows_with_db(struct ovn_desired_flow_table *flow_table)
-{
- if (hc_uuid) {
- ofctrl_remove_flows(flow_table, hc_uuid);
- }
}
@@ -34,6 +34,7 @@ struct simap;
struct sbrec_multicast_group_table;
struct sbrec_port_binding_table;
struct sset;
+struct local_nonvif_data;
/* OVN Geneve option information.
*
@@ -49,25 +50,23 @@ struct physical_ctx {
const struct ovsrec_bridge *br_int;
const struct sbrec_chassis_table *chassis_table;
const struct sbrec_chassis *chassis;
- const struct ovsrec_interface_table *iface_table;
const struct sset *active_tunnels;
struct hmap *local_datapaths;
struct sset *local_lports;
const struct simap *ct_zones;
enum mf_field_id mff_ovn_geneve;
struct shash *local_bindings;
+ struct simap *patch_ofports;
+ struct hmap *chassis_tunnels;
};
void physical_register_ovs_idl(struct ovsdb_idl *);
void physical_run(struct physical_ctx *,
struct ovn_desired_flow_table *);
-void physical_clear_unassoc_flows_with_db(struct ovn_desired_flow_table *);
-void physical_handle_port_binding_changes(struct physical_ctx *,
- struct ovn_desired_flow_table *);
void physical_handle_mc_group_changes(struct physical_ctx *,
struct ovn_desired_flow_table *);
-bool physical_handle_ovs_iface_changes(struct physical_ctx *,
- struct ovn_desired_flow_table *);
-bool get_tunnel_ofport(const char *chassis_name, char *encap_ip,
- ofp_port_t *ofport);
+void physical_handle_flows_for_lport(const struct sbrec_port_binding *,
+ bool removed,
+ struct physical_ctx *,
+ struct ovn_desired_flow_table *);
#endif /* controller/physical.h */